• Vue3的12种组件通信方式(附代码)


    vue官网查看
    (vue位于Github的地址:查看

    这篇文章的目的是让大家知道有这些方法可以用,所以不会深挖,接下来讲解的每种通信方式我都会附带一个简单的demo。
    觉得有帮助的话别忘了收藏

    开始

    Vue3的12种组件通信方式(下面是讲解顺序)

    • Props
    • emits
    • model
    • slot
    • provide / inject
    • bus
    • getCurrentInstance
    • expose / ref
    • Non-Props
    • Vuex
    • Pinia
    • mitt.js

    Props / emits

    /父组件
    <template>
      <b-Vue :msg="props父传子的消息" @changeMsg="changeMessage" />
    </template>
    
    <script setup>
    import bVue from './components/b.vue' 
    
    function changeMessage(data) {
        //data:'emits子传父的消息'
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    /子组件b.vue
    <template>
      <div>
       <div @click="handleClick"> {{ msg }} <div> //msg: 'props父传子的消息'
      </div>
    </template>
    <script setup>
    
    const props = defineProps({
      msg: {
        type: String,
        default: ''
      }
    })
    // 注册一个自定义事件名,向上传递时告诉父组件要触发的事件。
    const emit = defineEmits(['changeMsg'])
    
    function handleClick() {
      emit('changeMsg', 'emits子传父的消息')
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    v-model / emits

    • v-model 是 一个语法糖,通过Vue3的文档可以发现,这个指令的用法发生了一定的变化。在之前,xxxx.sync与之是很相似的,如今.sync指令已经被废除了,而是统一使用v-model这个指令。

    • v-model在组件身上使用

      • 相当有给子组件传递props[modelValue] = 10000

      • 相当于给子组件绑定自定义事件update:modelValue

    • 下面是使用v-model 与emits的通信示例 ( Vue官网中对于v-model的描述 )

    /父组件
    // Parent.vue
    <template>
      <b-Vue v-model:msg1="message1" v-model:msg2="message2" />
    </template>
    
    <script setup>
    import { ref } from 'vue'
    import bVue from './components/b.vue'
    
    const message1 = ref('父传子1')
    
    const message2 = ref('父传子2')
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // 子组件
    <template>
      <div><button @click="send1">修改msg1</button> {{msg1}}</div>
    
      <div><button @click="send2">修改msg2</button> {{msg2}}</div>
    </template>
    
    <script setup>
    import { ref } from 'vue'
    
    // 接收参   // 接收父组件使用 v-model 传进来的‘单’个值,必须用 modelValue 这个名字来接收
    const props = defineProps({
      msg1: String,
      msg2: String
    })
    必须用 update:参数||modelValue  这个格式来通知父组件修改值
    const emit = defineEmits(['update:send1', 'update:send2'])
    
    function send1() {
      emit('update:msg1', 'GOA1')
    }
    
    function send2() {
      emit('update:msg2', 'GOA2')
    }
    
    </script>
    
    • 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

    slot插槽

    • 插槽可以理解为传一段 HTML 片段给子组件。子组件将 元素作为承载分发内容的出口。
    • 插槽的基础用法非常简单,只需在 子组件 中使用 标签,就会将父组件传进来的 HTML 内容渲染出来。
    • 下面是slot进行通信的示例 (Vue官网关于slot的说明)
    /父组件
     <template>
      <!-- v-slot="{scope}" 获取子组件传上来的数据 -->
      <!-- :list="list" 把list传给子组件 -->
      <b-Vue v-slot="{scope}" :list="list">
        <div>
          <div> {{ scope.id}}</div>
          <div>{{ scope.text}}</div>
          <hr>
        </div>
      </b-Vue>
    </template>
    
    <script setup>
    import { ref } from 'vue'
    import bVue from './components/b.vue'
    
    const list = ref([
      { id: '1', text: '1'},
      { id: '2', text: '1'},
      { id: '3', text: '1'},
    ])
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    /子组件
    <template>
      <div>
        <!--:scope="item" 返回每一项 -->
        <slot v-for="item in list" :scope="item" />
      </div>
    </template>
    
    <script setup>
    const props = defineProps({
      list: {
        type: Array,
        default: () => []
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    provide / inject

    • 遇到父孙之间传值, props 和 emit 的方式会显得比较笨拙。这时就可以用 provide 和 inject 了。
    • provide 是在父组件里使用的,可以往下传值。
    • inject 是在子(后代)组件里使用的,可以网上取值。
    • 无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。
    • 下面是provide / inject进行实践的示例(Vue官网对provide / inject的描述)
    /<template>
      <b-Vue></b-Vue>
    </template>
    
    <script setup>
    import { ref, provide, readonly } from 'vue'
    import bVue from './components/b.vue'
    
    const name = ref('provide+readonly传的字')
    const msg = ref('provide传的字')
    
    // 使用readonly可以让子组件无法直接修改,需要调用provide往下传的方法来修改
    provide('name', readonly(name))
    
    provide('msg', msg)
    
    provide('changeName', (value) => {
      name.value = value
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    /<template>
      <div>
        <div>msg: {{ msg }}</div>
        <div>name: {{name}}</div>
        <button @click="handleClick">修改</button>
      </div>
    </template>
    
    <script setup>
    import { inject } from 'vue'
    
    const name = inject('name', '默认值')  //provide传的字
    const msg = inject('msg')
    const changeName = inject('changeName')
    
    function handleClick() {
     // 正确的方式
      changeName('虎躯一震')
      // 因为 msg 没被 readonly 过,所以可以直接修改值
      msg.value = '世界'
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    useAttrs

    • vue3框架提供了一个方法useAttrs方法,可以获取到组件身上的属性和事件,换个说法,useAttrs的功能于props的功能很类似,都是父组件传递数据给子组件。
    • 如果使用了props和useAttrs同时接收数据,props的优先级比useAttrs高
    • 下面为使用attrs进行通信的实践
    /<template>
      <b-Vue type="primary"  title="名字" ></b-Vue>
    </template>
     
    <script setup lang="ts"> 
    import bVue from './b.vue';
    const handleEvent = () => {}
    const handle = () => {}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
     /<template>
      <div>
        子组件:{{ attrs.title }}
      </div>
    </template>
     
    <script setup lang="ts">
    // 引入useAttrs方法:获取组件(attrsSon)身上的属性和事件
    import { useAttrs } from 'vue';
    // 此方法会返回一个对象
    let attrs = useAttrs()
    console.log('attrs',attrs); //组件身上的属性和事件  
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    eventBus

    • 如果你刚开始使用Vue3,很可能会发现,原本用得得心应手的eventBus突然不灵了,因为Vue3不再提供$on与emit函数,Vue实例不再实现事件接口。Vue 官方推荐使用 mitt 或 tiny-emitter。,或者自己手撸一个事件类
    • 这个vue实现eventBus的效果其实多种,我就不舞刀弄枪了,这里推荐一篇写的蛮好的博客(下面链接)
    • Vue 3 中如何优雅的使用eventBus(事件总线)

    getcurrentinstance

    • getcurrentinstance 是 vue 提供的一个方法,支持访问内部组件实例。
    • getCurrentInstance 只暴露给高阶使用场景,典型的比如在库中。
    • 强烈反对在应用的代码中使用 getCurrentInstance。请不要把它当作在组合式 API 中获取 this 的替代方案来使用。
    • getCurrentInstance 只能在 setup 或生命周期钩子中调用。
    • 只有在 development,即开发环境下才能获取到当前组件的实例,换句话说就是这个方法只是在开发环境下用于调试使用的;(适合在开发组件库的情况下使用,不适合日常业务开发中使用 )
    • 有兴趣的话可以去钻研一下,我这里就简单介绍下
    import {  getCurrentInstance } from 'vue'
    let num= null;
    num = getCurrentInstance 
    
    console.log(num)  //开发环境下可以获取到组件实例
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    expose / ref

    • 子组件可以通过 expose 暴露自身的方法和数据。

    • 父组件通过 ref 获取到子组件并调用其方法或访问数据。

    • 使用ref可以直接得到子组件的定义值,但要注意:在父组件要使用getCurrentInstance得到this,在子组件使用defineExpose暴露变量。

    /父拿到子的数据
    <template>
      <div>{{ msg }}</div>
      <button @click="callChildFn">调用子组件的方法</button>
      <b-Vue ref="com" />
    </template>
    
    <script setup>
    import { ref, onMounted } from 'vue'
    import bVue from './components/b.vue'
    
    const com = ref(null) 
    
    const msg = ref('')
    
    onMounted(() => {
      // 在加载完成后,将子组件的 message 赋值给 msg
      msg.value = com.value.message
    })
    
    function callChildFn() {
      // 调用子组件的 changeMessage 方法
      com.value.changeMessage('父改变参')
    
      // 重新将 子组件的message 赋值给 msg
      msg.value = com.value.message
    }
    </script>
    
    • 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
    /<template>
      <div>{{ message }}</div>
    </template>
    
    <script setup>
    import { ref } from 'vue'
    
    const message = ref('我是子的参')
    
    function changeMessage(data) {
      message.value = data
    }
    
    使用 defineExpose 向外暴露指定的数据和方法
    defineExpose({
      message,
      changeMessage
    })
    
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Non-Props

    • Non-Props 就是 非 Prop 的 Attribute。(Vue官网中的描述

    • 意思是在子组件中,没使用 prop 或 emits 定义的 attribute,可以通过 $attrs 来访问。常见的有 class 、style 和 id。

    /<template>
      <b-Vue msg="传子的数据" name="父亲" />
    </template>
    
    <script setup>
    import { ref } from 'vue'
    import bVue from './components/b.vue'
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    <template>
      <div :message="$attrs.msg">只绑定指定值</div>
      <div v-bind="$attrs">全绑定</div>
    </template>
    /有兴趣可以上手一下 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Vuex

    • Vuex和Pinia是Vue3中的状态管理工具,使用这两个工具可以轻松实现组件通信,由于这两个工具功能比较强大,这里就不做展示了,具体可以查阅文档 (改天有空补上)

    休息一下先 等会儿写

    在这里插入图片描述

  • 相关阅读:
    COLLABORATIVE DESIGNER FOR SOLIDWORKS® 新功能
    通过match看rust
    ES kibana 创建索引快速脚本
    将 Qt Designer 的 ui 文件转换为 PySide2 使用的.py 文件
    一切都在变
    uboot启动学习笔记六-uboot启动参数传递及第二阶段函数board_init_f
    嵌入式系统开发这六点硬件设计需要细心留意
    SpringMVC的视图
    微服务·架构组件之网关- Spring Cloud Gateway
    云积天赫AI全域营销系统,为品牌营销注入新活力
  • 原文地址:https://blog.csdn.net/weixin_45655820/article/details/132624600