vue组件之(父与子和非父子通信)

mac2024-05-08  30

父子组件通信

父子组件传值通信 假设第二层组件想和第一层组件进行通信,分析其传值过程 1、(第一层向第二层传值):父组件通过props传值到子组件,如此便实现父子组件向下通信 2、(第二层向第一层传值):子组件通过触发自定义事件$emit向父组件传值,如此便实现了父子组件向上通信

跨级组件通信

假设第三层组件想和第一层组件进行通信 1、(第一层组件向第三层组件传值)—禁止第一层直接传值到第三层,需要逐层传递,即1→2→3,此时便可以实现跨级组件向下通信 2、(第三层组件向第一层组件传值)—通过触发自定义事件将数据传递至第二层,然后第二层通过事件触发传递至第一层,如此逐层传递,便可以实现跨级组件向上通信

兄弟组件通信

假设第三层组件想和同层的另一个组件进行通信。 如果还是逐层传递至第二层,再由第二层传递至第三层,此时代码量十分累赘复杂,这也不符合Vue的定 义(Vue是一个轻量级的视图层框架) 引用官方文档: 因为基于组件树结构的事件流方式让人难以理解,并且在组件结构扩展的过程中会变得越来越脆弱。这种事件方式确实不太好,我们也不希望在以后让开发者们太痛苦。 官方推荐的状态管理方案是 Vuex。不过如果项目不是很大,状态管理也没有很复杂的话,使用 Vuex 有种杀鸡用牛刀的感觉,当然,这也是要根据自己的需求来的。 本节介绍下另一种方法,即bus/总线/发布订阅模式/观察者模式来解决

文档术语: 通过使用事件中心,允许组件自由交流,这个集中式的事件中间件就是 Bus总线。

语法: 在组件中使用$emit, $on, $off 分别来分发、监听、取消监听事件

父子组件通信:

<!-- html代码 --> <div id="demo" v-cloak> 一级{{moneyValue}} <my-demo :money="moneyValue" @pass="cutFn"></my-demo> </div> // vue代码 Vue.component('my-demo', { props: ["money"], data() { return { childMoney: this.money }, template: ` <div @click="cut"> 我是子组件我从父组件那里接受了{{childMoney}} </div>`, methods: { cut() { this.childMoney--; this.$emit("pass", this.childMoney) } } }) var demo = new Vue({ el: "#demo", data: { moneyValue: 6000 }, methods: { cutFn(option) { console.log(option) this.moneyValue = option } } })

知识点:【父子组件通信】 向上:自定义事件$emit 向下:props

兄弟|非父子组件通信

接下来继续介绍兄弟组件通信 再来梳理下需求,即当点击某个组件改变时,希望同时触发另外一个非父级组件改动,所以接下来需要在子组件绑定事件

<!-- html代码 --> <div id="demo"> <!-- 兄弟关系的通信 --> <my-btn :count="2"></my-btn> <my-btn :count="6"></my-btn> </div> // vue代码 // 1.第一步(注册全局bus总线): // prototype 作用域链 Vue.prototype.$bus = new Vue(); Vue.component('my-btn', { data(){ return{ childCount:this.count } }, props: { count: Number }, template: `<button @click="handleClick">按钮{{childCount}}</button>`, methods: { handleClick() { // alert(this.count) //2.第二步:通过中央事件线程$bus,分发事件属性$emit this.$bus.$emit('pass', this.childCount) } }, //3.结合生命周期钩子监听和接收分发的事件,监听事件属性$on。 mounted() { // 此时的this指向的全局 从新定义下就可以了 var _this=this; _this.$bus.$on('pass', function(option) { // console.log(option) // 到这浏览器是可以实现功能的但有一个报错 因为在子组件直接修改父组件是不对的要从新缓存下 _this.childCount=option; }) }, beforeDestroy(){ this.$bus.$off('pass'); } }) var demo = new Vue({ el: "#demo", })

总结: 步骤小结: 1、注册全局 b u s 使 用 空 V u e 实 例 作 为 中 央 事 件 总 线 n e w V u e ( ) , 注 册 全 局 bus 使用空Vue实例作为中央事件总线new Vue(),注册全局 bus使Vue线newVue()bus总线 2、分发 e m i t : 通 过 中 央 事 件 线 程 emit: 通过中央事件线程 emit线bus,A组件,分发事件属性 e m i t 3 、 监 听 emit 3、监听 emit3on: 结合生命周期钩子,B组件监听和接收分发的事件,监听事件属性 o n 。 4 、 取 消 on。 4、取消 on4off: 取消|清除监听事件,取消监听属性$off

引用官网的一句话: 父子组件的关系可以总结为 prop 向下传递,事件向上传递 父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息,如下图所示:

跨级组件通信

跨级通信方案 使用 a t t r s 和 attrs和 attrslisteners实现祖孙组件之间的数据传递,也就是多重嵌套组件之间的数据传递

版本注意: 本方法针对vue2.4版本及以上,使用 a t t r s 和 attrs和 attrslisteners来实现的 下面有一个小小的案例:

<!-- html代码 --> <div id="demo"> 最高级{{moneyValue}} <demo1 :money='moneyValue' @changeup="changeFn"></demo1> </div> // vue代码 Vue.component('demo2', { data(){ return { sonMoney: this.$attrs.money } }, template: ` <div> <h3 @click="goUp">我是二级的{{sonMoney}}</h3> </div>`, methods: { goUp(){ this.sonMoney--; this.$listeners.changeup(this.sonMoney); } } }) Vue.component('demo1', { inheritAttrs: false, template: ` <div> <h2>我是一级的</h2> <demo2 v-bind="$attrs" v-on="$listeners"></demo2> </div>` }) var demo = new Vue({ el: "#demo", data:{ moneyValue: 6000, }, methods: { changeFn(option) { this.moneyValue = option } } })

总结: (1)数值传递大概可以分为两种,即父子传值与非父子传值 (2)非父子传值包含:跨级传值、兄弟传值 (3)父向子传递:props (4)子向父传递: e m i t ( 5 ) 兄 弟 之 间 传 递 : 借 助 中 间 代 理 , 即 中 央 事 件 总 线 emit (5)兄弟之间传递:借助中间代理,即中央事件总线 emit5线bus 使用$emit, $on, $off 分别来分发、监听、取消监听事件 (6)跨级通信: a t t r s 可 以 获 取 父 作 用 域 传 入 的 值 ( 不 包 括 p r o p s 中 的 ) , attrs可以获取父作用域传入的值(不包括props中的), attrspropslisteners相当于父作用域的事件监听器,那我们就可以用这两个属性实现祖孙之间的数据通信

最新回复(0)