Fork me on Gitee

Vue中8中组件通信方式

 

 

 

 

如上图所示, A与B、A与C、B与D、C与E组件之间是父子关系; B与C之间是兄弟关系;A与D、A与E之间是隔代关系; D与E是堂兄关系(非直系亲属) 针对以上关系我们归类为:

    • 父子组件之间通信
    • 非父子组件之间通信(兄弟组件、隔代关系组件等)

 

一、props / $emit

父组件通过props的方式向子组件传递数据,而通过$emit 子组件可以向父组件通信。

1. 父组件向子组件传值

下面通过一个例子说明父组件如何向子组件传递数据:在子组件article.vue中如何获取父组件section.vue中的数据  articles:['红楼梦', '西游记','三国演义']

 // section父组件
 <template>
   <div class="section">
     <com-article :articles="articleList"></com-article>
   </div>
 </template>
<script>
 import comArticle from './test/article.vue'
 export default {
   name: 'HelloWorld',
   components: { comArticle },
   data() {
     return {
       articleList: ['红楼梦', '西游记', '三国演义']
     }
   }
 }
 </script>
 ​
 复制代码
 // 子组件 article.vue
 <template>
   <div>
     <span v-for="(item, index) in articles" :key="index">{{item}}</span>
   </div>
 </template>
<script>
 export default {
   props: ['articles']
 }
 </script>

总结: prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改都会失效并警告。

2. 子组件向父组件传值

对于$emit 我自己的理解是这样的: $emit绑定一个自定义事件, 当这个语句被执行时, 就会将参数arg传递给父组件,父组件通过v-on监听并接收参数。

 

 // 父组件中
 <template>
   <div class="section">
     <com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article>
     <p>{{currentIndex}}</p>
   </div>
 </template>
<script>
 import comArticle from './test/article.vue'
 export default {
   name: 'HelloWorld',
   components: { comArticle },
   data() {
     return {
       currentIndex: -1,
       articleList: ['红楼梦', '西游记', '三国演义']
     }
   },
   methods: {
     onEmitIndex(idx) {
       this.currentIndex = idx
     }
   }
 }
 </script>

// 子组件
 <template>
   <div>
     <div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</div>
   </div>
 </template>
<script>
 export default {
   props: ['articles'],
   methods: {
     emitIndex(index) {
       this.$emit('onEmitIndex', index)
     }
   }
 }
 </script>

 

 

 

二、 $children / $parent

使用方法

 // 父组件中
 <template>
   <div class="hello_world">
     <div>{{msg}}</div>
     <com-a></com-a>
     <button @click="changeA">点击改变子组件值</button>
   </div>
 </template>
<script>
 import ComA from './test/comA.vue'
 export default {
   name: 'HelloWorld',
   components: { ComA },
   data() {
     return {
       msg: 'Welcome'
     }
   },
 ​
   methods: {
     changeA() {
       // 获取到子组件A
       this.$children[0].messageA = 'this is new value'
     }
   }
 }
 </script>
 复制代码
 // 子组件中
 <template>
   <div class="com_a">
     <span>{{messageA}}</span>
     <p>获取父组件的值为:  {{parentVal}}</p>
   </div>
 </template>
<script>
 export default {
   data() {
     return {
       messageA: 'this is old'
     }
   },
   computed:{
     parentVal(){
       return this.$parent.msg;
     }
   }
 }
 </script>

注意:

要注意边界情况,如在#app上拿$parent得到的是new Vue()的实例,在这实例上再拿$parent得到的是undefined,而在最底层的子组件拿$children是个空数组。也要注意得到$parent$children的值不一样,$children 的值是数组,而$parent是个对象

总结

上面两种方式用于父子组件之间的通信, 而使用props进行父子组件通信更加普遍; 二者皆不能用于非父子组件之间的通信。

 

三、provideinject

 

见https://zhuanlan.zhihu.com/p/151831447

 

posted @ 2021-03-29 16:23  等风的羽毛  阅读(92)  评论(0编辑  收藏  举报
1