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

如上图
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做了一个完整的实现让我们很方便的进行父子组件之间的通信
<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>
|
<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。
$emit('remove',index)
@remove="hanldeRemove"
|
总结: prop只能从父组件传递到子组件。且数据为单向数据流。
2.$parent-> $child
vue的父子组件的第二种通信方式为$parent和$child
使用$parent可以获取到当前子组件的所有父组件实例
同理使用$child可以获取到当前父组件的所有子组件实例。
<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>
|
<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 作为接收变量的一方。
<template> <div> <component-b /> </div> </template> <script> import ComponentB from '../components/componentB.vue' export default { name: "componentA", provide: { zoo: "bird" }, components:{ ComponentB } } </script>
|
<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>
|
<template> <div> {{demo}} </div> </template> <script> export default { name: "componentC", inject: ['zoo'], data() { return { demo: this.zoo } } } </script>
|
由如上代码我们可以得出 provide和inject 不仅仅是父子组件之的通信。无论组件嵌套的有多深 只要他最终归属于ComponentA 那么就可以使用inject来获取到ComponentA中提供的zoo变量

如上图 是vue.js文档提供的关于provide和inject的阐述。
provide 和 inject 是非响应式的 因此 provide和inject 适用于传递一些非动态数据。
$ref-> $refs
ref可以用在任意的dom上也可以用在自定义的组件上。用在浏览器dom上获取的是dom的元素,用在自定义组件上获取的是组件的实例。通过获取的组件实例 我们可以使用到组件中任意的方法或属性
<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(){ this.$refs['comb']?.say() } } } </script>
|
<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非父子组件之间的通信
感谢您观看此篇博客,如果对您有帮助,希望能给个👍评论收藏三连!