组件间的通信是是实际开发中非常常用的一环,如何使用对项目整体设计、开发、规范都有很实际的的作用,我在项目开发中对此深有体会,总结下vue组件间通信的几种方式,讨论下各自的使用场景
文章相关技术预览prop、emit、bus、vuex、路由URL、provide/inject
注:以下介绍与代码环境: vue2.0+、vue-cli2
父子组件的通信是开发是最常用的也是最重要的,你们一定知道父子通信是用prop传递数据的,像这样:
//父组件,传递数据
//子组件,接受数据,定义传递数据的类型type与默认值default
props: {
inputIndex: {
type: Object,
default: function(){
return {}
}
},
inputName: {
type: String,
default: ''
}
父组件传递数据时类似在标签中写了一个属性,如果是传递的数据是data中的自然是要在传递属性前加 v-bind: ,如果传递的是一个已知的固定值呢
如果prop传到子组件中的数据是一个对象的话,要注意传递的是一个 对象引用 ,虽然父子组件看似是分离的但最后都是在同一对象下
在vue中子向父传递数据一般用**$emit**自定义事件,在父组件中监听这个事件并在回调中写相关逻辑
// 父组件监听子组件定义的事件
// 子组件需要返回数据时执行,并可以传递数据
this.$emit('editorEmit', data)
那么问题来了,我是不是真的有必要去向父组件返回这个数据,用自定义事件可以在当子组件想传递数据或向子组件传递的数据有变化需要重新传递时执行,那么另外一种场景, 父组件需要子组件的一个数据但子组件并不知道或者说没有能力在父组件想要的时候给父组件 ,那么这个时候就要用到组件的一个选项 ref :
vue中兄弟组件间的通信是很不方便的,或者说不支持的,那么父子组件中都有什么通信方式呢
// router index.js 动态路由
{
path:'/params/:Id',
component:Params,
name:Params
}
// 跳转路由
跳转路由
在跳转后的组件中用$route.params.id去获取到这个id参数为12,但这种只适合传递比较小的数据,数字之类的
在组件之外定义一个bus.js作为组件间通信的桥梁,适用于比较小型不需要vuex又需要兄弟组件通信的
import Vue from 'vue'
export default new Vue
import Bus from './bus.js'
export default {
methods: {
bus () {
Bus.$emit('msg', '我要传给兄弟组件们')
}
}
}
import Bus from './bus.js'
export default {
mounted() {
Bus.$on('msg', (e) => {
console.log(e)
})
}
}
注:以上两种使用场景并不高所以只是简略提一下,这两点都是很久以前写过,以上例子网上直接搜集而来如有错误,指正
规范:对于多人开发的大型应用规范的制定是至关重要的,对于所有人都会接触到的vuex对其修改数据调用数据都应有一个明确严格的 使用规范
对于vuex的使用场景也有一些争论,有人认为正常组件之间就是要用父子组件传值的方式,即使子组件需要使vuex中的数据也应该由父组件获取再传到子组件中,但有的时候组件间嵌套很深,只允许父组件获取数据并不是一个方便的方法,所以对于祖先元组件与子组件传值又有了新问题,vue官网也有一些方法解决,如下
provide/inject 除了正常的父子组件传值外,vue也提供了provide/inject
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效
官网实例
// 父级组件提供 'foo'
var Provider = {
provide: {
foo: 'bar'
},
// ...
}
// 子组件注入 'foo'
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
}
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
provide/inject还未在项目中应用过,后面会做尝试