vue组件间的九种通信方式

代码 代码 1465 人阅读 | 0 人回复

<
媒介

Vue组件真例间的感化域是互相自力的,而凡是一个页里是由许多个组件组成,那些组件能够又嵌套了组件,构成了一个干系网图,它们的干系多是像下图中一样,大抵分为两种利用场景,女子组件间通讯战非女子组件间通讯,女子组件间通讯又分为间接女子干系战直接女子干系。vue供给了多种通讯办法,针对差别的通讯需供,挑选最适宜的通讯方法能赞助我们进步开辟服从。本文扼要介绍了八种通讯方法和合用场景,纪录下正在进修中的支货。
214750v26jt14h5ho420t4.jpg

女子组件间的通讯

props战$emit

那是女子组件正在传参时中经常使用的一种方法,女组件经由过程v-bind传进参数,子组件经由过程props去吸取,子组件经由过程内乱建的$emit办法传进变乱名去触收一个变乱,女组件经由过程v-on像监听本死DOM变乱一样去监听那个变乱。
  1. // 女组件CompFather
  2. <template>
  3.         <div>
  4.                 <comp-son
  5.                         :title-name="title_name"
  6.                         @changeTitle="changeTitle"
  7.                 />
  8.                 <div>女组件的title_name:{{ title_name }}</div>
  9.         </div>
  10. </template>
  11. <script>
  12.         import CompSon from "./CompSon";
  13.         export default {
  14.                 name: "CompFather",
  15.                 components: {CompSon},
  16.                 data() {
  17.                         return {
  18.                                 title_name: "我是初初值"
  19.                         }
  20.                 },
  21.                 methods: {
  22.                         changeTitle(val) {
  23.                                 this.title_name = val;
  24.                         }
  25.                 }
  26.         }
  27. </script>
复造代码
  1. // 子组件CompSon
  2. <template>
  3.    <div>
  4.       <div>子组件的titleName:{{titleName}}</div>
  5.       <button @click="changeTitle">改动</button>
  6.    </div>
  7. </template>
  8. <script>
  9.    export default {
  10.       name: "CompSon",
  11.       props: {
  12.          titleName: {
  13.             type: String,
  14.             required: true
  15.          }
  16.       },
  17.       methods: {
  18.          changeTitle() {
  19.             this.$emit("changeTitle", "我变了");
  20.          }
  21.       }
  22.    }
  23. </script>
复造代码
合用场景:合用于间接女子干系(中心无嵌套组件)的组件间举办通讯。
$attrs战$listeners

$attrs包罗了女感化域中没有做为 prop 被辨认 (且获得) 的 attribute 绑定 (class 战 style 除中)。当一个组件出有声明任何 prop 时,那里会包罗一切女感化域的绑定 (class 战 style 除中),而且能够经由过程 v-bind="$attrs" 传进内乱部组件。
  1. // Comp1.vue
  2. <template>
  3.    <comp2
  4.       :flag="flag"
  5.       :id="id"
  6.       :msg="msg"
  7.    />
  8. </template>
  9. <script>
  10.    import Comp2 from "./comp2";
  11.    export default {
  12.       name: "comp1",
  13.       components: {Comp2},
  14.       data() {
  15.          return {
  16.             id: 1,
  17.             msg: "comp1&#39;s msg",
  18.             flag: true
  19.          }
  20.       }
  21.    }
  22. </script>
复造代码
  1. // Comp2.vue
  2. <template>
  3.    <div>
  4.       <div>comp2的$attrs:{{$attrs}}</div>
  5.       <comp3 v-bind="$attrs" />
  6.    </div>
  7. </template>
  8. <script>
  9.    import Comp3 from "./comp3";
  10.    export default {
  11.       name: "comp2",
  12.       components: {Comp3},
  13.       props: {
  14.          flag: Boolean
  15.       },
  16.       mounted() {
  17.          console.log(this.$attrs); // { "id": 1, "msg": "comp1&#39;s msg" }
  18.       }
  19.    }
  20. </script>
复造代码
  1. // Comp3.vue
  2. <template>
  3.    <div>comp3的$attrs:{{ $attrs }}</div>
  4. </template>
  5. <script>
  6.    export default {
  7.       name: "comp3",
  8.       props: {
  9.          msg: String
  10.       },
  11.       mounted() {
  12.          console.log(this.$attrs);  // { "id": 1 }
  13.       }
  14.    }
  15. </script>
复造代码
那里Comp2的props吸取了Comp1传进的flag,因而Comp2中的$attrs出有flag参数,Comp3吸取了msg,因而$attrs只要id。
合用场景:组件之间跨级传参,可使用$attrs属性,如许使得代码愈加简约,更利于保护。
$listeners包罗了女感化域中的 (没有露 .native 润饰器的) v-on 变乱监听器。它能够经由过程 v-on="$listeners" 传进内乱部组件。
当我们要启拆一个input规范的组件时,我们能够经由过程.native的方法监听它的本惹事件。
  1. // App.vue
  2. <add-item v-model="input_val" />
  3. <my-input @input.native="inputData" :value="value" />
复造代码
  1. // MyInput.vue
  2. <template>
  3.    <input
  4.          type="text"
  5.          :value="value"
  6.          @input="$emit(&#39;input&#39;,e.target.value)"
  7.       >
  8. </template>
  9. <script>
  10.    export default {
  11.       name: "MyInput",
  12.       props: {
  13.          value: String
  14.       },
  15.    }
  16. </script>
复造代码
但假如此时的input被label标签包裹了一层,input没有再是根组件时,女组件的.native将监听生效,因而vue给我们供给了$listeners属性去打点那个成绩。
  1. // MyInput.vue
  2. <template>
  3.    <input
  4.          type="text"
  5.          :value="value"
  6.          @input="$emit(&#39;input&#39;,e.target.value)"
  7.       >
  8. </template>
  9. <script>
  10.    export default {
  11.       name: "MyInput",
  12.       props: {
  13.          value: String
  14.       },
  15.    }
  16. </script>      value:{{ value }}         
复造代码
以下是利用$listeners属性举办监听:
  1. // App.vue
  2. <add-item v-model="input_val" />
  3. <my-input @input.native="inputData" :value="value" />   
复造代码
  1. <template>
  2.    <label>
  3.       value:{{ value }}
  4.       <input
  5.          type="text"
  6.          :value="value"
  7.          v-on="inputListeners"
  8.       >
  9.    </label>
  10. </template>
  11. <script>
  12.    export default {
  13.       name: "MyInput",
  14.       props: {
  15.          value: String
  16.       },
  17.       computed: {
  18.          inputListeners: function () {
  19.             const vm = this
  20.             // `Object.assign` 将一切的工具兼并为一个新工具
  21.             return Object.assign({},
  22.                // 我们从女级增加一切的监听器
  23.                this.$listeners,
  24.                // 然后我们增加自界说监听器,
  25.                // 或覆写一些监听器的举动
  26.                {
  27.                   // 那里确保组件共同 `v-model` 的事情
  28.                   input: function (event) {
  29.                      vm.$emit(&#39;input&#39;, event.target.value)
  30.                   }
  31.                }
  32.             )
  33.          }
  34.       },
  35.    }
  36. </script>
复造代码
合用场景:当需求监听子组件的本惹事件,且子组件多是颠末重构的组件时,可使用$listeners去替代.native监听,固然也不单是包罗本惹事件监听器,只是正在那里监听本惹事件比力适宜,我们还有别的方法去干事件监听。
$children/$parent/$root

$children是当前真例的间接子组件,没有包管挨次,数组挨次纷歧定是子组件正在该女组件中的衬着挨次,也没有是呼应式的。
假如当前真例有女组件的话,$parent则是当前真例的女真例。
$root是当前组件树的根 Vue 真例。假如当前真例出有女真例,此真例将会是其本人。经由过程this.$root去会见。
  1. [/code] 缺陷:$children获得到的真例没有包管挨次,因而当有多个子组件时能够获得到的没有是本人念要的那一个。当组件嵌套多级时,能够会呈现$parent.$parent.$parent...的状况,关于后绝保护没有友爱。
  2. 合用场景:尽管利用别的方法去替代$parent/$chilren
  3. [size=3]ref[/size]
  4. ref 被用去给元素或子组件注册援用疑息。援用疑息将会注册正在女组件的 $refs 工具上。假如正在一般的 DOM 元素上利用,援用指背的便是 DOM 元素;假如用正在子组件上,援用便指背组件真例。
  5. [code]// App.vue
  6. <add-item v-model="input_val" />
  7. <my-input @input.native="inputData" :value="value" />  
复造代码
合用场景:当利用element-ui组件时,可用于挪用组件办法,例如el-table组件的挑选表格项,排序等等。
v-model

一个组件上的 v-model 默许会利用名为 value 的 prop 战名为 input 的变乱,可是像单选框、复选框等规范的输进控件能够会将 value attribute 用于差别的目标。model 选项能够用去制止如许的辩说。
  1. // App.vue
  2. <add-item v-model="input_val" />
  3. <my-input @input.native="inputData" :value="value" />
复造代码
  1. <template>
  2.    <div class="add">
  3.       <input
  4.          :value="value"
  5.          type="text"
  6.          placeholder="What needs to be done?"
  7.          @input="inputVal"
  8.       >
  9.    </div>
  10. </template>
  11. <script>
  12.    export default {
  13.       name: "AddItem",
  14.       // 假如对应的props字段名没有叫value,则需求界说model属性去指定女组件的v-modal绑定的是哪一个值
  15.       /*model: {
  16.          prop: "value1",
  17.          event: "input"
  18.       },*/
  19.       props: {
  20.          value: {
  21.             type: String,
  22.             required: true
  23.          }
  24.       },
  25.       methods: {
  26.          inputVal(e) {
  27.             this.$emit("input", e.target.value);
  28.          }
  29.       }
  30.    }
  31. </script>
复造代码
合用场景:v-model合用于正在启拆input规范的组件时,用于给数据举办单背绑定,假如没有利用v-model,则需求正在女组件增长一个办法去监听变乱然后改动女组件中的值,隐得十分费事且没有简约。
Sync润饰符

sync取v-model十分相同,也是合用于需求子组件改动女组件的值时。 :isShow.sync="isShow"实际上是 @update:isShow="bol=>isShow=bol"语法糖
  1.             <template>
  2.    <div class="add">
  3.       <input
  4.          :value="value"
  5.          type="text"
  6.          placeholder="What needs to be done?"
  7.          @input="inputVal"
  8.       >
  9.    </div>
  10. </template>
  11. <script>
  12.    export default {
  13.       name: "AddItem",
  14.       // 假如对应的props字段名没有叫value,则需求界说model属性去指定女组件的v-modal绑定的是哪一个值
  15.       /*model: {
  16.          prop: "value1",
  17.          event: "input"
  18.       },*/
  19.       props: {
  20.          value: {
  21.             type: String,
  22.             required: true
  23.          }
  24.       },
  25.       methods: {
  26.          inputVal(e) {
  27.             this.$emit("input", e.target.value);
  28.          }
  29.       }
  30.    }
  31. </script>
复造代码
  1.              我是一个子组件,我正在红色的陆地里!<template>
  2.    <div class="add">
  3.       <input
  4.          :value="value"
  5.          type="text"
  6.          placeholder="What needs to be done?"
  7.          @input="inputVal"
  8.       >
  9.    </div>
  10. </template>
  11. <script>
  12.    export default {
  13.       name: "AddItem",
  14.       // 假如对应的props字段名没有叫value,则需求界说model属性去指定女组件的v-modal绑定的是哪一个值
  15.       /*model: {
  16.          prop: "value1",
  17.          event: "input"
  18.       },*/
  19.       props: {
  20.          value: {
  21.             type: String,
  22.             required: true
  23.          }
  24.       },
  25.       methods: {
  26.          inputVal(e) {
  27.             this.$emit("input", e.target.value);
  28.          }
  29.       }
  30.    }
  31. </script>
复造代码
provide/inject

那对选项需求一同利用,以许可一个先人组件背其一切子孙后世注进一个依靠,不管组件条理有多深,并正在其高低游干系成立的工夫里一直见效。
provide正在女组件中将子组件要利用的数据扔出,然后正在子组件中inject注进要利用的数据,它没有像利用props需求层层传递,中心没有需求那个数据的处所也需求声明,provide战inject只重视“泉源”战“尽头”,次要用于正在下阶组件库中利用,正在平居的开辟中普通没有合用的缘故原由是没有便利逃溯“泉源”,没有明白是哪一层声明的战利用了。
子孙层中的provide会笼盖祖女层中不异key的属性值。
provide 选项该当是一个工具或返回一个工具的函数。该工具包罗可注进其子孙的 property。
inject选项该当是一个字符串数组或一个工具,from是选自祖女组件provide的哪一个值的key,default指定一个默许值。
  1. // 女组件
  2. provide: ["message"],
  3.    
  4. // 子组件
  5. inject: {
  6.     msg: {
  7.         from: "message",
  8.         default: "default value"
  9.     }
  10. }
复造代码
  1. // 女组件CompFather<template>
  2.    <div class="add">
  3.       <input
  4.          :value="value"
  5.          type="text"
  6.          placeholder="What needs to be done?"
  7.          @input="inputVal"
  8.       >
  9.    </div>
  10. </template>
  11. <script>
  12.    export default {
  13.       name: "AddItem",
  14.       // 假如对应的props字段名没有叫value,则需求界说model属性去指定女组件的v-modal绑定的是哪一个值
  15.       /*model: {
  16.          prop: "value1",
  17.          event: "input"
  18.       },*/
  19.       props: {
  20.          value: {
  21.             type: String,
  22.             required: true
  23.          }
  24.       },
  25.       methods: {
  26.          inputVal(e) {
  27.             this.$emit("input", e.target.value);
  28.          }
  29.       }
  30.    }
  31. </script>
复造代码
  1. // 子组件 CompSon
  2. <template>
  3.    <div>
  4.       子组件
  5.    </div>
  6. </template>
  7. <script>
  8.    export default {
  9.       name: "CompSon",
  10.       inject: ["msg"],
  11.       mounted() {
  12.          console.log(this.msg);  // 女组件msg
  13.       }
  14.    }
  15. </script>
复造代码
provide 战 inject 绑定并非可呼应的。那是决心为之的。但是,假如您传进了一个可监听的工具,那末其工具的 property 仍是可呼应的。例如provide战inject的是一个工具时,该数据是可呼应的。
  1. // 当provide/inject的是一个工具时,是可呼应的,子组件改动值,女组件也会改动,女组件改动子组件也会改动
  2. provide() {
  3.    return {
  4.       msg: this.msg
  5.    }
  6. },
  7.    
  8. data() {
  9.         return {
  10.                 msg: {
  11.                         title: "女组件msg"
  12.                 }
  13.         }
  14. }
复造代码
合用场景:合用于启拆下阶组件,先人真例没有体贴哪一个后世真例会用到,后世真例没有体贴数据滥觞于哪一个先人真例。
非女子组件间的通讯

中心变乱总线 bus

利用中心变乱总线实践便是创立一个vue真例,利用那个vue真例去传递动静。
利用方法一:
  1. // 界说一个bus文件
  2. import Vue from "vue";
  3. const bus = new Vue();
  4. export default bus;
复造代码
  1. // 引进bus文件
  2. import bus from "@/bus";
  3. bus.$emit("myEvent", "bus msg")
复造代码
  1. // 引进bus文件
  2. import bus from "@/bus";
  3. bus.$on("myEvent", data => {
  4.     console.log(data);
  5. });
复造代码
利用方法两:
  1. // main.js
  2. import Vue from &#39;vue&#39;
  3. import App from &#39;./App.vue&#39;
  4. Vue.prototype.$bus = new Vue();
  5. new Vue({
  6.   render: h => h(App),
  7. }).$mount(&#39;#app&#39;)
复造代码
  1. // 收收变乱
  2. this.$bus.$emit("myEvent", "bus msg");
  3. // 领受变乱
  4. this.$bus.$on("myEvent", data => {
  5.     console.log(data);
  6. })
复造代码
合用场景:合用于没有是出格年夜的单页里使用跨级跨兄弟组件间通讯。
VueX

当我们正在开辟年夜型但单页使用时,组件间需求频仍利用修正某些值,这时候候利用组件间传参便隐得十分冗杂混乱,且倒霉于办理保护,vue为打点那一成绩供给了VueX那个形态办理东西,我们只需求将多个组件需求同享的形态放VueX及第止同一办理,构成一个齐局单例办理形式,便可完成组件数据同步。
214750nt15zrtjfi4iffmj.png

VueX的将要同一办理的形态放正在state中,如许正在援用了VueX的页里中就可以获得到形态,actions次要是处置例如背景恳求的一些同步操纵,包管数据的同步,经由过程dispatch办法挪用actions中的办法,当获得同步的数据以后再经由过程commit挪用mutations中的办法改动state。没有要正在组件中经由过程$store.state间接修正state数据,如许Devtools是监控没有到的,要颠末mutations才能够。
那里只是扼要介绍通讯方法,具体的利用办法参见
总结

通讯方法合用场景props/$emit间接女子组件传值$attrs/$listeners$attrs非间接女子组件间传值,$listeners监听本惹事件$children/$parent普通用别的方法替代,没有便利保护ref可用于挪用下阶组件办法,如注册element-ui组件援用v-model启拆需求单背绑定的组件时用v-modal举办传参sync润饰符用于女子组件间,子组件需求改动女组件值时provide/inject多用于下阶组件库,平居开辟普通没有利用,倒霉于代码保护中心变乱总线合用于跨级或兄弟组件间通讯。VueX用于年夜型单页里中多个组件需求同享统一形态时。
免责声明:假如进犯了您的权益,请联络站少,我们会实时删除侵权内乱容,感谢协作!
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
回复 关闭延时

使用道具 举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则