本篇文章相对全面并简洁地介绍了Vue中组件间传值的几种方式
一、父传子
-
标签传值
-
传递:
当子组件在父组件中当做标签使用的时候,给子组件绑定一个自定义属性,值为需要传递的数据
<son :sex="男"></son>
-
接收:
在子组件内部通过props接收。props有2种接收方式:
-
通过数组进行接收:
props:["sex"]
- **通过对象进行接收**(推荐): > 通过对象接收可以给接收的值增加数据类型限制,在较大的项目开发的时候,能利用它避免不少的错误。 ```js props:{ sex:{ type:String, //"限制数据类型" default: "男", //"默认值" required:true //"必须传递" } } // 然后就可以{{sex}}进行取值
-
-
-
provide/inject 跨组件传值
数据的流向只能是向下传递(包括爷传孙)
严格的来讲是跨组件传值,但是也是父传子的一种方式
-
传递:provide
这个配置必须在传值方进行使用(祖先级),用来定义后代组件所需要的一些属性和方法
- 第一种写法:provide是一个函数,返回一个对象
provide(){ return{ username:"Hehe" } }
第二种写法:直接写成对象:
provide:{ username:"Hehe" }
-
-
接收:inject
必须在后代组建中进行使用,用来获取根组件定义的跨组件传来的数据
<h2> 根组件传来的数据为{{username}} </h2>
-
第一种写法:
inject:["username"]
-
也可以写成对象(推荐):
同属性传值,对象的方式给接收的值增加数据类型限制
inject:{ username:{ from:"传值的组件" default:"默认值" }
-
}
```
二:子传父
-
事件抛发传值
利用事件抛发的传参原理,进行传值
本质是父组件向子组件传递一个方法,子组件调用这个方法,并传递参数实现子传父
-
传递
在子组件内部通过this.$emit("自定义事件的名称",需要传递的参数)来进行数据的传递
原理:this.$emit 将原先侦听好的事件进行抛发,并传递参数。
this.$emit("sonToFather","子向父传的值")
-
接收
当子组件在父组件中当做标签使用的时候给当前子组件绑定一个自定义事件,值为需要接收值得函数,这个函数要特别的注意不允许加()
<Father @sonToFather="callback">{{val}}</Father>
methods:{ callback(val){ this.val = val } },
注意事项:因为此方法基于事件抛发原理,所以必须先接收才能传递,二者同时进行亦可。
-
-
作用域插槽
通过将数据绑定到组件上的方式,让父组件得以接收
-
子组件中传递
<!-- 在子组件中定义作用域插槽 --> <template> <div id="child"> <!-- 在slot中通过v-bind的方式绑定数据 --> <slot :title="title"></slot> </div> </template> <script> export default{ name:"Child", data(){ return{ title:"我是子组件的标题" } } } </script>
-
-
父组件中接收
<template> <Child> <template v-slot:title="slotProps"> <h2>{{slotProps.title}}</h2> </template> </Child> </template>
三:非父子传值
-
EventBus——事件总线
原理:给要实现通信的组件双方绑定同一个新的Vue实例,如此便可以调用同一个实例里的
on 方法传值,类似于子传父
缺点:这样虽然可以做到跨组件传值,但传递方法有一定的不足——绑定一整个实例却只用到里边的几个方法,造成一定的性能浪费
Vue.prototype.$eventBus = new Vue();
-
传递
this.$eventBus.$emit("handler","我是传递的值")
-
接收
this.$eventBus.$on("handle",(value)=>{ this.value = value; })
-
-
手动封装事件订阅(优化版)
原理同上,只不过将用到的方法自己封装一遍,更节省性能
// main.js 文件 import observer from "./observer" Vue.prototype.$observer = observer
// observer文件 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 }vuex
vuex
跨组件传值的最好的解决方案:共享存储区域。放在单独章节...