共计 4151 个字符,预计需要花费 11 分钟才能阅读完成。
一、父子组件通信
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
https://juejin.im/post/6844903977100804103#heading-7
https://juejin.im/post/6844904048118726663#heading-21