vue3常用的几个组件通信方式,props, emit, provide/inject,

props(父传子,多用于 子组件需要渲染父组件中的数据)

【父】
<div>
    <comp-son :name="name" :age="age" />  //向子组件传值
</div>

setup() {
        const state = reactive({
            name: "Jack",
            age: 18  
        })
        return {
            ...toRefs(state)
        }
    },
【子】
export default {
    name: "CompSon",
    // props: ['name', 'age'],  //接收父组件的传值:简写形式
    props: {  //接收父组件的传值:详细形式
        name: String,  //传入值类型
        age: {
            type: Number,  // 传入值类型,多个类型写法 type: [Number, String]
            required: true,  // 是否必须
            default: 18,  // 该属性没有进行传值时的默认值
        }
    },
    setup(props, context) {
        console.log(props.name)
        console.log(props.age)

    },
};

拓展:父组件调用子组件中定义的方法

https://www.cnblogs.com/huihuihero/p/16931598.html

emit(子传父,多用于 子组件修改父组件的数据)

【父】
<div>
    <comp-son @setName="setName" />  //向子组件传函数
</div>

setup() {
        const state = reactive({
            name: "Jack",
        })

        function setName(name){
            state.name = name
        }

        return {
            ...toRefs(state)
        }
    },
【子】
export default {
    name: "CompSon",
    setup(props, context) {
        // context可获取三个属性,分别为context.attrs、context.emit、context.slots
        // 推荐使用解构赋值写法 setup(props, { emit }){ emit("setName", "Bob") } 
        context.emit("setName", "Bob")  //接收父组件函数并调用
    },
};

v-model:xxx(父传子+子传父:多用于 父子组件数据之间的双向绑定)

这个v-model其实是个语法糖。就是当子组件emit触发的事件名固定写死为update的时候,可以使用v-model去监听。
此种方式有一点需要注意下,见下图

【父】
<div>
    <comp-son v-model:value="name" />  //建立双向绑定
</div>

setup() {
        const state = reactive({
            name: "Jack",
        })

        return {
            ...toRefs(state)
        }
    },
【子】
export default {
    name: "CompSon",
    props: {
        value: {
            type: String,
            default: "",
        },
    },
    setup(props, { emit }) {  // 这里是对context进行解构赋值
        function changeValue(){
                emit("update:value", "Bob")  //改变父子组件双向绑定的值,注意这里是固定写法"update:xxx"(冒号后面不要有空格等,如"update: xxx"这样是错的)
        }
    },
};

v-model这种方式有一点需要注意下(个人见解)

当使用v-model:xxx="xxxx" 传入的值是一个对象或数组时。
通过emit("update:xxx", xxxx) 更新时,建议重新const一个array或object且需要改变指针指向,而不是用reactive或者ref里定义的动态值

【推荐的】以数组为例,对象需要深拷贝
const arr = [...state.sectionList]
emit("update:xxx", arr)

【不推荐的】此种方式会使得xxx与state.sectionList之间指针指向一致。从而导致后续state.sectionList的改动实时映射到xxx中,造成不必要的问题
emit("update:xxx", state.sectionList)

provide/inject(父传子/孙,多用于 父组件传子孙组件这种深层级的组件传值)

import { provide } from 'vue'
// 父组件中
provide('info', theInfo)


import { inject } from 'vue'
// 子/孙组件中
const theInfo = inject('info')

vuex或mitt(多用于兄弟组件之间的传值)

mitt

【官方文档】https://www.npmjs.com/package/mitt

【安装插件】
yarn add mitt


【新建src/utils/bus/bus.jsimport mitt from "mitt";
const videoBus = mitt();
const liveBus = mitt();  //这里多声明了一个liveBus是为了说明,可以声明多个bus全局使用,且多个bus之间互不干扰(就算emit相同名称)

export { videoBus, liveBus };


【兄弟组件1import { videoBus, liveBus } from "@/utils/bus/bus"

videoBus.emit("toggle", "视频切换了")
liveBus.emit("toggle","直播切换了")  //使用相同emit toggle,但互不干扰
//注,为保证组件间通信的准确性,建议将emit传值放在nextTick中

【兄弟组件2import { videoBus, liveBus } from "@/utils/bus/bus"
videoBus.on("toggle",(info)=>{
    console.log(info)  //视频切换了
})
liveBus.on("toggle",(info)=>{
    console.log(info)  //直播切换了
})

【重要】
页面销毁前,需要销毁监听
liveBus.off("toggle")

清除所有
liveBus.all.clear()

【参考博客】
https://juejin.cn/post/7056688469719908388
posted @   huihuihero  阅读(1091)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
历史上的今天:
2019-12-02 iframe
点击右上角即可分享
微信分享提示