• 六、Vue基础之六



    一、兄弟组件传参和Bus

    有两个组件A,B和父组件P,A想传参到B必须先传到父组件P中,再通过父组件P传给B。
    上面这种方式麻烦。

    Bus:发布订阅模式

    二、Mitt

    vue3中 o n , on, on,off和$once实例方法已被移除,组件实例不再实现事件触发接口,因此大家熟悉的EventBus便无法使用了,我们可以使用Mitt库,其实就是发布订阅模式的设计。

    安装

    npm install mitt -S
    
    • 1

    在Main.ts中引入mitt

    import { createApp } from 'vue'
    import App from './App.vue'
    import mitt from 'mitt'
    
    const Mit = mitt()
    
    const app = createApp(App)
    
    // 让在TS中有提示
    declare module 'vue' {
        export interface ComponentCustomProperties {
            $Bus: typeof Mit
        }
    }
    
    app.config.globalProperties.$Bus = Mit
    
    app.mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在A组件中发布事件

    <template>
        <h2>A组件h2>
        <button @click="emit">emitbutton>
    template>
    
    <script setup lang='ts'>
    import { getCurrentInstance } from 'vue'
    
    const instance = getCurrentInstance()
    // 发布事件
    const emit = () => {
        instance?.proxy?.$Bus.emit('on-click1', 'mitt1')
        instance?.proxy?.$Bus.emit('on-click2', 'mitt2')
    }
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在B组件订阅发布的事件

    <template>
        <h2>B组件</h2>
        {{str}}
    </template>
    
    <script setup lang='ts'>
    import { ref, getCurrentInstance } from 'vue';
    const instance = getCurrentInstance()
    let str = ref('')
    
    // 订阅事件
    /*
    instance?.proxy?.$Bus.on('on-click1', (strA)=>{
        console.log(strA, 'B组件')
        str.value = strA as string
    })
    */
    
    // type函数,str发布事件携带的数据
    /*
    instance?.proxy?.$Bus.on('*', (type, str) => {
        console.log(type, str, 'B组件')
    })
    */
    
    const Bus = (str: any) => {
        console.log(str, 'B组件')
    }
    instance?.proxy?.$Bus.on('on-click1', Bus)
    instance?.proxy?.$Bus.off('on-click1', Bus)
    instance?.proxy?.$Bus.all.clear()
    
    </script>
    
    <style lang='scss' scoped>
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    三、TSX

    我们之前是用Template去写我们的模板,现在可以扩展一种TSX风格
    安装插件

    npm install @vitejs/plugin-vue-jsx -D
    
    • 1

    vite.config.ts中配置一下

    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import vueJsx from '@vitejs/plugin-vue-jsx'
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [vue(), vueJsx()]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    tsconfig.json中配置一下

    "jsx": "preserve",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",
    
    • 1
    • 2
    • 3

    在src下建一个App.tsx

    const renderDom = () => {
        return(
            <div>
                <h2>hello, tsx</h2>
            </div>
        )
    }
    
    export default renderDom
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在App.vue中使用这个tsx模板

    <template>
        <renderDom>renderDom>
    template>
    
    <script setup lang="ts">
    import renderDom from './App'
    script>
    
    <style lang="scss" scoped>
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在tsx中一些指令的用法和template中有些许的不一样。
    app.tsx

    
    import { ref } from 'vue'
    
    let v = ref<string>('')
    
    let arr = [1, 2, 3]
    
    const renderDom = () => {
        return(
            <div>
                {/*
                
                

    {v.value}

    */
    } {/* v-for不支持,用js的思想来写 */} {/* { arr.map(v=>{ return ({v},) }) } */} </div> ) } export default renderDom
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    四、v-model

    给自定义组件去绑定一个v-model
    App.vue

    <template>
        <div>
            <h1>我是app.vue父组件h1>
            <p>isShow:{{isShow}}p>
            <div><button @click="isShow=!isShow">开关button>div>
            <p>{{text}}p>
            <hr>
            
            
            <vModela v-model="isShow" v-model:textValue="text">vModela>
        div>
        
    template>
    
    <script setup lang="ts">
    import { ref } from 'vue'
    import vModela from './components/v-model.vue'
    const isShow = ref<boolean>(true)
    const text = ref<string>('hello')
    
    script>
    
    <style lang="scss" scoped>
    
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    v-model.vue

    <template>
    
        <div class="model" v-if="modelValue">
            
            <div class="close"><button @click="close">关闭button>div>
            <h3>我是v-model子组件 dialogh3>
            
            <div>内容: <input @input="change" :value="textValue" type="text">div>
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    
    // 使用modelValue来接受父组件传过来的v-model的值
    defineProps<{
        modelValue: boolean,
        textValue: string
    }>()
    
    // 子组件点击关闭,将窗口关闭,并且将父组件的isShow改成false
    const emit = defineEmits(['update:modelValue', 'update:textValue'])
    const close = () => {
        emit('update:modelValue', false)
    }
    const change = (e:Event) => {
        const target = e.target as HTMLInputElement
        emit('update:textValue', target.value)
    }
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    五、自定义指令directive

    通过给子组件绑定自定义指令去获取子组件的一些数据,在挂载完成之后获取得到子组件的一些数据。
    App.vue

    <template>
        <div>
            
            <A v-move:aaa.kk="{ background: 'red' }">A>
        div>
        
    template>
    
    <script setup lang="ts">
    import { ref, Directive, DirectiveBinding } from 'vue'
    import A from './components/A.vue'
    
    type Dir = {
        background: string
    }
    
    
    const vMove:Directive = {
        created(){
            console.log('created')
        },
        beforeMount(){
            console.log('beforeMount')
        },
        // 可以通过这个指令拿到子组件的一些数据
        // mounted(...args: Array){
        //     console.log('mounted')
        //     console.log(args)
        // },
        mounted(el:HTMLElement, dir:DirectiveBinding<Dir>){
            el.style.background = dir.value.background
        },
        beforeUpdate(){
            console.log('beforeUpdate')
        },
        updated(){
            console.log('update')
        },
        beforeUnmount(){
            console.log('beforeUnmount')
        },
        unmounted(){
            console.log('unmounted')
        }
    
    }
    
    script>
    
    <style lang="scss" scoped>
    
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    子组件A.vue

    <template>
        <div class="box">
            A组件
        div>
    template>
    
    <script setup lang='ts'>
    
    script>
    
    <style lang='scss' scoped>
    .box{
        width: 200px;
        height: 200px;
        border: 1px solid yellowgreen
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    六、自定义Hooks

    Vue3自定义Hook,主要用来处理利用代码逻辑的一些封装,将多个相同的逻辑抽离出来,各个组件只需要引入,就能实现一次写代码,多组件受益的效果。hooks是函数。
    vueuse开源库

    <template>
        <div>
            
            <A aa="888" title="title">A>
        div>
        
    template>
    
    <script setup lang="ts">
    import A from './components/A.vue'
    
    script>
    
    <style lang="scss" scoped>
    
    style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    A.vue

    <template>
        <div class="box">
            A组件
        div>
    template>
    
    <script setup lang='ts'>
    import { useAttrs } from 'vue'
    let attr = useAttrs()
    console.log(attr)
    script>
    
    <style lang='scss' scoped>
    .box{
        width: 200px;
        height: 200px;
        border: 1px solid yellowgreen
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Hooks就是定义一个函数,暴露给其他组件使用。

  • 相关阅读:
    二进制手表
    指针升级版!!!我在这里传授艰深道法,诸位道友可愿与我一同修行?
    中电金信技术实践|配置中心组件的升级历程
    【著作阅读笔记】《代码整洁之道》对Sql类的重构引发的思考
    本地构建、打包elasticjob-console3.1.0+
    学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计 汉语言文学设计题材网页
    postman登录鉴权之接口测试
    第十八章《JDBC》第1节:JDBC简介
    Web App、Hybrid App、Native App 横向对比
    LeetCode //C - 909. Snakes and Ladders
  • 原文地址:https://blog.csdn.net/weixin_42710036/article/details/127644844