一、父子组件通信
1、props和$emit/$on
(1) 父组件向子组件传参
在父组件使用v-bind 传值,子组件中使用props接收参数
(2) 子组件给父组件传递数据——自定义事件
子组件通过$emit方法,触发父组件v-on的事件
- 优点
使用简单,是父子组件最基础的传参方法。
props提供了类型检查支持
$emit不会修改到别的组件的同名事件,它只会触发父级事件,这里和event-bus不同
- 缺点
多层组件需要逐层传递
不能解决多个组件依赖同一个状态的问题
2、$refs,$parent, $children
(1)子组件可以使用$parent 访问父组件实例,父组件可以通过$children对子组件进行操作。
缺点:一个组件的子组件可能不是唯一的,返回值是一个数组。所以无法确定子组件的顺序。
(2)ref如果作用在DOM元素上,引用指向的是DOM元素;如果作用在子组件上,引用指向的是子组件实例,可以直接访问子组件的数据和调研子组件的方法。
3、.sync 修饰符
开发过程中,我们一般使用props/emit 实现双向绑定,为了方便起见,在2.3.0版本中提供了一个语法糖.sync修饰符。
<text-document v-bind:title.sync="doc.title"></text-document>
二、兄弟组件通信
1、eventBus(中央事件总线)
evnetBus的原理是新建一个新的Vue实例,然后通过bus.$emit触发事件,bus.$on监听触发的事件,实现通信和参数的传递。
初始化bus
Vue.prototype.$EventBus = new Vue()
或:
import Vue from 'vue'
export default Bus = new Vue()
父组件:
<template>
<div>
<p>bus 实例父组件: {{msg}}</p>
<span @click="fatherBus">按钮</span>
<busChild />
</div>
</template>
<script>
import Bus from '../assets/js/bus'
import busChild from './busChild'
export default {
data() {
return {
msg: 'bus demo'
}
},
components: {
busChild
},
methods:{
fatherBus(){
Bus.$emit('BusTo', this.msg)
}
}
}
</script>
子组件:
<template>
<div>
<p>Bus 实例子组件: {{child}}</p>
</div>
</template>
<script>
import Bus from '../assets/js/bus.js'
export default {
data(){
return {
child: ''
}
},
mounted (){
Bus.$on('BusTo', (data)=>{
this.child= data
})
}
}
</script>`
缺点:(1)页面刷新时,与之相关的eventBus会被销毁。
(2)由于使用一个Vue实例,定义同一个事件名,并没有用off销毁。
优点: 解决多层组件之间繁琐的事件传播
三、隔代组件通信
1、provide 和inject
provide和inject成对使用。作用是允许一个祖先组件向其所有子孙后代注入一个依赖。
适用于祖先组件和后代组件之间的通信,无论组件的层次有多深,其上下游关系始终生效。
provide选项应该是一个对象或者返回对象的函数。
inject选项应该是字符串数组或对象。
<template>
<div class="provide">
<p>provide 实例父组件: </p>
<span @click="clickHandler">按钮+1</span>
<injectTest />
</div>
</template>
<script>
import injectTest from './injectTest'
export default {
components: {
injectTest
},
provide (){
return {
test: this
}
},
data (){
return {
testData: 1
}
},
methods: {
clickHandler (){
++ this.testData
console.log(this.testData)
}
}
}
</script>
子组件:
<template>
<div>
<p>inject 子组件实例:</p>
<span>{{test.testData}}</span>
</div>
</template>
<script>
export default {
inject: ['test'],
mounted () {
console.log('this.test', this.test)
}
}
</script>
缺点: 子组件获取父组件属的状态,父组件无法获取子组件的状态。
2、$attrs 和$listeners
$attrs:包含了父组件在子组件上设置的属性,不包含prop传递的属性和class、style。
$listeners:包含了父作用域中的(不含.native修饰器)v-on事件监听器。即通过$listeners可以将祖先组件中的事件,传递到后代组件。
祖先组件index:
<template>
<child1 :attr1="attr1" :attr2="attr2" @changeInfo="changeInfo"/>
</template>
<script>
import child1 from './components/child1'
export default {
data () {
return {
attr1: 'hi, attr',
attr2: 'hello, attr'
}
},
methods: {
changeInfo(){
console.log('attr and')
}
}
}
</script>
子组件child1:
<template>
<p>父组件传值attr1: {{attr1}}</p>
//通过$attrs将祖先组件的属性传递到后代组件child2中,通过$listeners将祖先组件中的事件传递到child2中 //从而child2可以访问祖先组件的属性和事件
<child2 v-bind="$attrs" v-on="$listeners"/>
</template>
<script>
import child2 from './child2'
export default {
components: {
child2
},
props: ['attr1'],
mounted (){
console.log('父组件中this.$attrs', this.$attrs)
console.log('父组件中this.$listeners', this.$listeners)
}
}
</script>
子组件child2:
<template>
<div>
<p>祖先组件传参: {{$attrs}}</p>
</div>
</template>
<script>
export default {
name: 'attrDemo',
inheritAttrs: false,
mounted (){
console.log('父组件中this.$attrs', this.$attrs) console.log('父组件中this.$listeners', this.$listeners)
this.$emit('changeInfo')
}
}
</script>
补充:
新增属性inheritAttrs,默认情况下父作用域的不被认作props的attribute绑定将会“回退”且作为普通的HTML属性应用在子组件根元素上。
如果不希望组件的根元素继承特性,可以设置inheriAttrs:false。
3、vuex
vuex是vue提供的状态管理模式。它采用集中存储管理所用组件的状态。适用于多个组件状态共享,项目比较大的情况。
优缺点:
- 优点
解决了多层组件依赖同一个状态的问题
单向数据流
- 缺点
页面重新加载时,数据需要重新写入
增加额外的代码体积,不适用在简单业务需求
参考文档:
$atttr 和$listener:
https://www.jianshu.com/p/4649d317adfe
https://blog.csdn.net/songxiugongwang/article/details/84001967
https://www.jianshu.com/p/a388d38f8c69
https://segmentfault.com/a/1190000022708579
eventBus:
https://segmentfault.com/a/1190000021707081
https://zhuanlan.zhihu.com/p/72777951
https://juejin.im/post/6844904167597686791#heading-2
https://juejin.im/post/6856359634039963656
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。