运行环境
组件通信
父组件 => 子组件
- 属性
props
// child
props: { msg: String }
// parent
<Helloworld msg="welcome to your Vue.js App"/>
- 特性
$attrs
// child: 未在子组件props中声明的属性,可在子组件中使用 “$atttrs.属性名” 的方式引用
<p>{{ $attrs.foo }}</p>
...
props: {}
...
// parent
<Helloworld foo="foo" />
- 引用
$refs
// parent
<Helloworld ref="hw"/>
...
// 注意该方法需要等待组件的DOM替换完成后再调用
//一般而言会在mounted生命周期内再调用,或者使用this.$nextTick(() => { /*该回调内调用*/ })
this.$refs.hw // 返回的内容是子组件(Helloworld)的数据对象,可通过this.$refs.hw.xx 获取子组件属性名和方法,并对值进行修改或调用
...
- 子元素
$children
// parent
...
this.$children // 会返回所有的子组件数据对象集合
// !!!但是子元素不保证顺序
...
子组件 => 父组件:自定义事件
- 子组件内调用组件本身的
$emit
方法
// child: 子组件调用自身的$emit方法,第一个参数是父组件需要绑定的方法名第二个参数是父组件方法会接收的传参
...
this.$emit('add', good)
...
// parent
<Cart @add="cartAdd($event)"></Cart>
...
cartAdd(el, good) {
/* 第一个参数是节点数据对象,第二个是子组件传递的参数 */
}
...
兄弟组件:通过共同祖辈组件
通过共同的祖辈组件搭桥,
p
a
r
e
n
t
或
parent或
parent或root
// borther1: 监听该方法被触发后执行 hanlde 回调函数
this.$parent.$on('foo', handle)
// borther2:派发该方法
this.$parent.$emit('foo')
祖先和后代之间
由于嵌套层数过多,传递props不切实际,vue提供了 provide/inject
API 完成该任务
- provide/inject: 能够实现祖先给后代传值
// ancestor - 祖辈
provide() {
return { foo: 'foo' }
}
// descendant - 后代
inject: ['foo']
任意两个组件之间:事件总线 或 vuex
- 事件总线: 创建一个Bus类负责事件派发、监听和回调管理
// Bus: 事件派发、监听和回调管理
class Bus {
constructor() {
// 每个key值代表一个被监听的方法, 对应的value值表示当该方法被派发时需要执行的所有回调
this.callbacks = {}
}
// 监听
$on (name, fn) {
/* 第一个参数为方法名, 第二个参数为回调函数 */
// callbacks初始值为空对象,因此先确定callbacks对象内是否创建name属性
this.callbacks[name] = this.callbacks[name] || []
// 将回调函数添加至数组中
this.callbacks[name].push(fn)
}
// 派发
$emit (name, args) {
/* 第一个参数:方法名 第二个参数:派发时的传参 */
// 如果该方法存在,遍历数组,执行每一个回调函数
if (this.callbacks[name]) {
this.callbacks[name].forEach(cb => cb(args))
} else {
console.log('该方法还未被监听')
}
}
}
// main.js
Vue.prototype.$bus = new Bus()
// child1
this.$bus.$on('foo', handle)
// child2
this.$bus.$emit('foo', args)