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.js】
import mitt from "mitt";
const videoBus = mitt();
const liveBus = mitt(); //这里多声明了一个liveBus是为了说明,可以声明多个bus全局使用,且多个bus之间互不干扰(就算emit相同名称)
export { videoBus, liveBus };
【兄弟组件1】
import { videoBus, liveBus } from "@/utils/bus/bus"
videoBus.emit("toggle", "视频切换了")
liveBus.emit("toggle","直播切换了") //使用相同emit toggle,但互不干扰
//注,为保证组件间通信的准确性,建议将emit传值放在nextTick中
【兄弟组件2】
import { 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
分类:
Vue3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2019-12-02 iframe