vue组件传值(8种方法)----props、$emit()、手动封装事件订阅observer、事件总线(Eventbus)、vuex、亲兄弟传值、provide/inject、插槽作用域
1、父传子
传递:当子组件中在父组件中当做标签使用的时候,给子组件绑定一个自定义属性,值为需要传递的数据
接收:在子组件内部通过props进行接收,props接收的方式有2种:
①通过数组进行接收 props:["属性"]
②通过对象进行接收 props:{
属性:{
(1)type:限制数据的类型
(2)default:默认值
(3)required:布尔值,和default二选一
}
}
步骤:
①在父组件中给子组件标签上添加自定义属性:
<son :custom="100"></son>
②子组件中通过props接收:
props:["custom"]
③接收到的custom可以直接在标签中使用 {{custom}}
注意:今后只要看到props就要想到这个属性是用来接收外部数据的。
2、子传父
①接收:当子组件在父组件中当做标签使用的时候,给当前子组件绑定一个自定义事件,值为需要接收值的函数,这个函数不允许加 ()
②传递的过程:在子组件内部通过this.$emit("自定义事件名称",需要传递的参数)来进行数据的传递
步骤:
①父组件中给需要接收参数的子组件绑定自定义事件,值为需要接收值的函数:
<son @handler="handlerMsg"></son>
methods:{
handlerMsg(value){
console.log(value)// 这个值是通过this.$emit()触发传来的
}
}
②子组件中触发自定义事件:
this.$emit("handler",100);
3、非父子传递
第一种方法:通过给vue原型上添加一个公共的vue实例对象(vue实例对象上有$on()和$emit()),需要传递的一方调用$emit(),需要接收的一方调用$on()。
步骤:
①main.js中:
Vue.prototype.$observer=new Vue();
②需要传递的组件中:
this.$observer.$emit("handler",100);
③需要接收的组件中:
this.$observer.$on("handler",(value)=>{
console.log(value)
});
注意:在挂载前(created)进行$on()绑定,先绑定好,再触发。
*第二种方法:手动封装事件订阅observer
步骤:
①src下新建observer.js:
const eventList={}; const $on=function (eventName,callback) { if(!eventList[eventName]){ eventList[eventName]=[]; } eventList[eventName].push(callback); } const $emit=function(eventName,params){ if(eventList[eventName]){ let arr=eventList[eventName]; arr.forEach((cb)=>{ cb(params); }); } } const $off=function(eventName,callback){ if(eventList[eventName]){ if(callback){ let index=eventList[eventName].indexOf(callback); eventList[eventName].splice(index,1); }else{ eventList[eventName].length=0; } } } export default{ $on, $emit, $off }
②main.js中用手动封装的observer替代new Vue()
import observer from "./observer.js";
Vue.prototype.$observer=observer;
③在需要传递的组件中用this.$observer.$emit()触发自定义事件:
this.$observer.$emit("customHandler","需要传递的值");
④在需要接收的组件中用this.$observer.$on()绑定自定义事件:
this.$observer.$on("customHandler",this.toggle);
⑤清除自定义事件
beforeDestroy() { this.$observer.$off('customHandler') },
第三种方法:事件总线(Eventbus)
步骤:
①先创建一个空实例:
let bus=new Vue();
②通过bus.$on()绑定自定义事件:
bus.$on("customHandler",要触发的函数);
③通过bus.$emit()来触发自定义事件:
bus.$emit("customHandler");
*第四种方法:vuex(后续)
注:如果是亲兄弟:(父传子和子传父)
步骤:
①父组件中声明data数据 state:true ,将state通过props传给其中一个子组件:
<two :show="state"></two>
props:show
此时show的值随着state的变化而变化
②再通过另一个子组件去改变父组件的state:
标签上绑定自定义事件:
<one @customHandler="toggle"></one>
再在子组件内部通过$emit()触发customHandler事件:
this.$emit("customHandler");
provide / inject(提供/注入)跨组件传值,其实就是父传子
provide / inject:依赖注入。可以实现跨组件传值,数据的流向只能是向下传递,就是大范围有效的props
provide:这个配置项必须要在父级进行使用,用来定义后代组件所需要的一些属性和方法。
语法:
provide:{
}
// 推荐
provide(){ return{ } }
inject:这个配置项必须在后代组件中使用,用来获取根组件定义的跨组件传值的数据。
语法:
inject:[]
// 推荐
inject:{ key:{ from:"父组件名称", default:默认值 } }
插槽 slot
作用:默认情况下组件内部包裹的内容是不会显示的,如果需要进行显示则需要通过插槽来进行显示。
1、匿名插槽:没有名字的插槽(v-slot:default)
v-slot
在组件内部通过<slot></slot>进行接收
步骤:
①App.vue中在组件标签中添加template标签(里面可以写多个标签),写上v-slot属性
<Header>
<template v-slot>
<p>111</p>
<p>222</p>
</template>
</Header>
②在Header.vue组件中通过<slot></slot>开辟一块空间:
<div class="header">
<slot></slot>
</div>
2、命名插槽:有名字的插槽
v-slot:slotName
在组件内部通过<slot name="slotName"></slot>来进行接收
步骤:
①给插槽指令加上名字:
<template v-slot:slotName>
<p>111</p>
</template>
②slot标签添加name属性:
<div class="header">
<slot name="slotName"></slot>
</div>
如果还有匿名插槽template,就在Header.vue中用<slot></slot>再开辟一块空间接收匿名插槽。
3、插槽作用域:(子传父)
v-slot:slotName(名字可写可不写,如果不写默认是default)="变量(这个变量是一个对象)"
作用:让组件来提供自身需要显示的内容
步骤:
①App.vue中template中设置v-slot="props"(props是一个对象):---------父
<template v-slot="props">
<h2>{{props.info}}</h2>
</template>
②Header.vue中slot标签绑定自定义属性info:----------子,info属性的值提供给父组件中的props.info
<div class="header">
<slot :info="'111'"></slot>
</div>
③在template中可以通过props.info拿到子组件中传来的值
如果要用命名插槽:
App.vue:直接在v-slot后面加上 :slotName
Header.vue:<slot name="slotName" :info="'111'"></slot>
分类:
vue
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结