chaihongjun.me

Vue组件之间通信总结

组件之间的通信涉及到父子,兄弟和隔代之间。

  1. 父组件给子组件传递数据,通过父组件的数据绑定到子组件的prop进行传递

父组件:

 <template> <div> <h1>父组件</h1> <children :childrenProp="fatherData"></children> </div> </template>  <script> import Children from './Children' export default{   name:'Father',     components:{         Children     },     data(){         return{             fatherData:'来自父组件'         }     }     } </script>  <style scoped> div {   border: 1px solid #ccc; } </style>

子组件:

 <template> <div> <h1>子组件</h1> {{childrenProp}}  </div> </template>  <script> export default{   name:'Children',     props:{        childrenProp:String      },     data(){         return{             childrenData:'子组件'         }     }     } </script>  <style scoped> div {   border: 1px solid #ccc;   margin: 10px; } </style>

结果:

QQ截图20191112140640.png


  1. 子组件传值给父组件,通过子组件的$emit,"发射"一个"事件"并携带子组件的数据给父组件。

子组件:

 <template>   <div>     <h1>子组件</h1>     {{childrenProp}}   </div> </template> <script> export default {   name: "Children",   data() {     return {       childrenData: "来自子组件"     };   },   created() {     /*         this 表示当前的组件        CustomEvent是一个自定义的事件         这里子组件创建完了之后,向父组件“发射”了一个自定义的事件,并且同时传递了数据     */     this.$emit("CustomEvent", this.childrenData);   } }; </script> <style scoped> div {   border: 1px solid #ccc;   margin: 10px; } </style>

父组件:

 <template>   <div>     <h1>父组件</h1>       <!-- 父组件对子组件的自定义事件进行监听,并且设置对应的事件处理程序 -->     <children @CustomEvent="EventProcess"></children>       <!-- 打印子组件传来的数据 -->     {{dataFromChildren}}   </div> </template>  <script> import Children from "./Children"; export default {   name: "Fat",   components: {     Children   },   methods: {       /*         子组件传递来数据通过父组件的事件处理程序处理        子组件数据传给父组件       */      EventProcess(dataFromChildren) {       this.dataFromChildren = dataFromChildren;     }   },   data() {     return {       dataFromChildren: ""     };   } }; </script>  <style scoped> div {   border: 1px solid #ccc; } </style>

结果:

QQ截图20191112145348.png

  1. 另外一种就是兄弟组件之间的传递,一般的使用方法是结合子组件传递父组件,父组件传递子组件。或者使用eventBus方式(通过eventBus去发送和接收自定义事件并处理)

    EventBus.js

 import Vue from "vue"; export default new Vue();

兄弟组件一(发送数据的一方):

 <template>   <div>     <h1>BroOne组件</h1>     <p>{{BroOneData}}</p>   </div> </template> <script> // 导入 EventBus 实际是一个Vue对象 import EventBus from "./EventBus.js"; export default {   name: "BroOne",   data() {     return {       BroOneData: "来自BroOne组件"     };   },   mounted() {     /*         子组件创建完了之后,触发(EventBus)实例事件     */     EventBus.$emit("CustomEvent", this.BroOneData);     console.log(this.BroOneData);   } }; </script> <style scoped> div {   border: 1px solid #ccc;   margin: 10px; } </style>

另外一个兄弟组件(接收数据的一方):

 <template>   <div>     <h1>BroTwo组件</h1>     <p>{{fromSblingsData}}</p>   </div> </template> <script> // 导入 EventBus 实际是一个Vue对象 import EventBus from "./EventBus.js"; export default {   name: "BroTwo",   data() {     return {       fromSblingsData: ""     };   },   created() {     /*           另外一个兄弟组件,监听事件并处理     */     let _this = this;     EventBus.$on("CustomEvent", function(fromSblingsData) {       _this.fromSblingsData = fromSblingsData;     });   } }; </script> <style scoped> div {   border: 1px solid #ccc;   margin: 10px; } </style>

结果:

QQ截图20191112160439.png

  1. 第四种方式就是通过Vue生态的vuex,这里不做赘述,有点类似eventBus。

  1. 除了以上父子兄弟关系的组件还有一种是祖孙关系,祖孙关系的数据传递使用前面的eventBus也行,另外就是Vue 2.4+新增加的$attrs,在子组件上v-bind=$attrs,可以将当前组件的属性,除了prop传递和classstyle之外的属性一并传给子组件。

Father.vue

 <template>   <div class="father">     <p>father.vue</p>     <son       :msg="msg"       :sonProperOne="fromFatherOne"       :sonProperTwo="fromFatherTwo"       @notify="log"       v-on="$listeners"     ></son>   </div> </template>  <script> import Son from "./Son"; export default {   name: "Father",   data() {     return {       msg: "Father.vue",       fromFatherOne: "fromFatherOne",       fromFatherTwo: "fromFatherTwo"     };   },   methods: {     log() {       console.log("son called");     }   },   components: {     Son   },   created() {     console.log("---------- father created ----------");     console.log("this.$attrs:");     console.log(this.$attrs);   } }; </script>  <style scoped> .father {   border: 1px solid #ccc;   margin: 10px; } </style>

Son.vue

 <template>   <div class="son">     <p>Son.vue</p>     prop:{{msg}}     <grand       :msg="sonmsg"       :grandProperOne="fromSonOne"       :grandProperTwo="fromSonTwo"       @notify="log"       v-bind="$attrs"     ></grand>     this.$attrs:{{$attrs}}   </div> </template>  <script> import Grand from "./grand"; export default {   name: "Son",   inheritAttrs: true,   data() {     return {       sonmsg: "Son.vue",       fromSonOne: "fromSonOne",       fromSonTwo: "fromSonTwo"     };   },   props: {     msg: String   },   components: {     Grand   },   methods: {     log() {       console.log("grand called");     }   },   created() {     console.log("---------- Son created ----------");     console.log("this.$attrs:");     console.log(this.$attrs);     this.$emit("notify"); //  告诉父组件要触发事件   } }; </script>  <style scoped> .son {   border: 1px solid #ccc;   margin: 10px; } </style>

Grand.vue

 <template>   <div class="son">     <p>Grand.vue</p>     prop:{{msg}}     <grandson       :msg="grandmsg"       :grandSonProperOne="fromGrandOne"       :grandSonProperTwo="fromGrandTwo"       v-bind="$attrs"       @notify="log"     ></grandson>     this.$attrs:{{$attrs}}   </div> </template>  <script> import grandson from "./grandson"; export default {   name: "grand",   inheritAttrs: true,   data() {     return {       grandmsg: "Son.vue",       fromGrandOne: "fromGrandOne",       fromGrandTwo: "fromGrandTwo"     };   },   props: {     msg: String   },   components: {     grandson   },   methods: {     log() {       console.log("grandson called");     }   },   created() {     console.log("---------- grand created ----------");     console.log('grandson 绑定 v-bind="$attrs"');     console.log("this.$attrs:");     console.log(this.$attrs);     this.$emit("notify"); //  告诉父组件要触发事件   } }; </script>  <style scoped> .son {   border: 1px solid #ccc;   margin: 10px; } </style>

Grandson.vue

 <template>   <div class="grandson" @click="log">     <p>grandson.vue</p>     prop:{{msg}}     <br />     this.$attrs:{{$attrs}}   </div> </template>  <script> export default {   name: "grandson",   inheritAttrs: true,   data() {     return {};   },   props: {     msg: String   },   methods: {     log() {       console.log("grandson clicked");     }   },   created() {     console.log("---------- grandsonson created ----------");     console.log("this.$attrs:");     console.log(this.$attrs);     this.$emit("notify"); //  告诉父组件要触发事件   } }; </script>  <style scoped> .grandson {   border: 1px solid #ccc;   margin: 10px; } </style>

结果:

QQ截图20191112164018.pngQQ截图20191112164018



知识共享许可协议本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。作者:柴宏俊»