前言

使用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 {
animal: this.zoo
}
},
components: {
ComponentC
}
}
</script>
// ComponentC.vue C组件
<template>
<div>
{{demo}}
</div>
</template>
<script>
export default {
name: "componentC",
inject: ['zoo'],
data() {
return {
demo: this.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非父子组件之间的通信

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