阅读 94

Vue组件通信八种方式(父子组件之间的通信)

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

前言

使用Vue.js进行项目开发 组件之间的通信是必不可少的知识点。组件作为vue中重要的一个模块,组件之间又是自己的独立的作用域 那么组件之间的数据传递就变得尤其重要了。(数据驱动视图。你说重不重要嘛~ 嘿!)

组件关系

企业微信截图_16329949375821.png 如上图
A组件里面包含B组件和C组件 那么可以称这种关系为父子组件关系 那么B和C呢? B和C可以称之为兄弟组件关系 B->D C->E 都可以称作父子组件关系D->E 称作兄弟组件关系 A-D A-E 这种则称作祖孙组件关系 因此我们可以分为两种类型

父子组件之间的通信
非父子组件之间的通信(祖孙关系,兄弟关系)
复制代码

了解如上关系之后我们分类来进行展开。

父子组件之间的通信

Vue中实现父子组件之间的通信方法一共有3种,分别是:

1.props->$emit
2.$parent->$children
3.provide->inject(不仅仅是父子组件)
复制代码

1.props -> $emit

作为Vue最常用的一个通信方式,想必大家都不陌生,这是vue官网最推荐的一种父子组件关系的通信方式 vue做了一个完整的实现让我们很方便的进行父子组件之间的通信

// ComponentA(父组件)
<template>
 <div class="fruit_shop">
 <component-b 
 @remove="handleRemove"
 :fruitList="fruitList" />
 </div>
</template>

<script>
import componentB from './test/componentB.vue'
export default {
 name'ComponentA',
 components: { componentB },
 data() {
    return {
        fruitList: ['苹果''香蕉''西瓜']
    }
  },
  method:{
  handleRemove(params){
     this.fruitList.splice(params,1)
  }
  }
}
</script> 
复制代码
//  componentB(子组件)
<template>
 <div>
 <span v-for="(item, index) in fruitList" @click="$emit('remove',index)" :key="index">{{item}}</span>
 </div>
</template>
 
<script>
export default {
 props: ['fruitList']
}
</script>
复制代码

如上代码 父组件通过v-bind将fruitList传递给子组件 子组件利用 props接受到父组件传递的fruitList然后遍历渲染 我们在遍历的标签span 中添加一个点击事件 触发 子组件向父组件的通信方式$emit

//子组件
//'remove'表示要通信的名称  index则表示通信传递的参数 参数可以是任意类型。
$emit('remove',index)
//父组件
//父组件接受到子组件的通信 并调用对应的事件方法
@remove="hanldeRemove"
复制代码

总结: prop只能从父组件传递到子组件。且数据为单向数据流。

2.$parent-> $child

vue的父子组件的第二种通信方式为$parent$child 使用$parent可以获取到当前子组件的所有父组件实例 同理使用$child可以获取到当前父组件的所有子组件实例。

// ComponentA(父组件)
<template>  
<div class="fruit_shop">
<span>{{message}}</span>
<component-b />
<button @click='changeChildMsg'>修改子组件的值</button>
</div> 
</template> 
<script> 
import componentB from './test/componentB.vue'
export default {
  name'ComponentA',  
  components: { componentB }, 
  data() { 
    return {  
      message:'hello world!'
           }
     },
   method:{
     changeChildMsg(){
       this.$child[0].childMsg ='hello,child Component!'
        }
         } 
           } 
</script>
复制代码
//  componentB(子组件) 
<template> 
<div>  
<hr/>
<span>{{parentMsg}}</span>
</div> 
</template>
<script>
export default{  
 name:'ComponentB',
 data(){
   return {
     childMsg:'hello,parent Component!'
       }
         },
     computed:{
       parentMsg(){
         return this.$parent.message
       }
    }
  </script>
复制代码

如上代码,子组件通过computed计算属性获取到父组件实例中的message
父组件通过click事件修改子组件实例中的childMsg 并修改为'hello child Component!' 值得注意的是使用$parent获取到的父组件实例是一个对象,使用$child获取到的子组件实例是一个数组。 对于大型vue项目 总结: 对于大型的vue项目,组件之间错综复杂。不建议使用$parent$child进行组件通信。

3.provide -> inject

provide和inject是vue提供的另一种组件通信方式 但它却不局限于父子组件之间的通信。 简单理解: provide 我们可以当作组件全局提供的变量 inject 作为接收变量的一方。

// componentA.vue A组件
<template>
 <div>
    <component-b />
 </div>
</template>
 
<script>
 import ComponentB from '../components/componentB.vue'
 export default {
 name"componentA",
 provide: {
  zoo"bird"
 },
 components:{
  ComponentB
 }
 }
</script>
复制代码
// componentB.vue  B组件
<template>
 <div>
 {{animal}}
 <component-c />
 </div>
</template>
 
<script>
 import ComponentC from '../components/componentC.vue'
 export default {
 name"componentB",
 inject: ['zoo'],
 data() {
  return {
  animalthis.zoo
  }
 },
 components: {
  ComponentC
 }
 }
</script>
复制代码
// ComponentC.vue C组件
<template>
 <div>
 {{demo}}
 </div>
</template>
<script>
 export default {
 name"componentC",
 inject: ['zoo'],
 data() {
  return {
  demothis.zoo
  }
 }
 }
</script>
复制代码

由如上代码我们可以得出 provide和inject 不仅仅是父子组件之的通信。无论组件嵌套的有多深 只要他最终归属于ComponentA 那么就可以使用inject来获取到ComponentA中提供的zoo变量

provide inject.png 如上图 是vue.js文档提供的关于provide和inject的阐述。 provide 和 inject 是非响应式的 因此 provide和inject 适用于传递一些非动态数据。

$ref-> $refs

ref可以用在任意的dom上也可以用在自定义的组件上。用在浏览器dom上获取的是dom的元素,用在自定义组件上获取的是组件的实例。通过获取的组件实例 我们可以使用到组件中任意的方法或属性

// ComponentA(父组件)
<template>  
<div class="fruit_shop">
<component-b  ref="comb"/>
<button @click='useChildComponent'>修改子组件的值</button>
</div> 
</template> 
<script> 
import componentB from './test/componentB.vue'
export default {
  name'ComponentA',  
  components: { componentB }, 
   method:{
     useChildComponent(){
     //refs是所有被ref标记的集合。$refs是一个对象。我们拿到名为comb的ref即是组件B的实例。
     this.$refs['comb']?.say()
        //控制台打印 "hello,parent Component!"
        }
         } 
           } 
</script>
复制代码
//  componentB(子组件) 
<template> 
<div>

</div> 
</template>
<script>
export default{  
 name:'ComponentB',
 data(){
   return {
     childMsg:'hello,parent Component!'
       }
         },
    method:{
      say(){
        console.log(this.childMsg)
        }
      }
    }
  </script>

复制代码

总结:$refs$ref适用于父子组件之间的通信 拿到refs中定义的ref即是拿到了组件的实例。通过实例直接调用组件的方法或访问数据

最后

Vue组件通信的父子组件之间的通信到这里就结束了。 下期我们将一起探讨 Vue非父子组件之间的通信

感谢您观看此篇博客,如果对您有帮助,希望能给个👍评论收藏三连!

文章分类
前端
文章标签