vue组件通信方式

197 阅读1分钟

父子组件

  • props
  • emit /on (子传父)
  • parent/children
  • ref
  • attrs/listeners(2.4.0 新增)

兄弟组件

  • $parent
  • $root
  • eventBus
  • vuex

跨层级关系

  • eventBus
  • vuex
  • provide/inject

1. 父组件 => 子组件

a. 属性props

// 子组件
props: {msg: String}
// 父组件
<Helloworld msg="welcome to vue"></Helloworld>

b. 特性$attrs

// 子组件
<p>{{ $arres.foo }}</p>
// 父组件
<HelloWorld foo="这是一个特殊属性" />

c. 引用refs

// 父组件
<Helloworld ref="fo" />
mounted () {
    this.$refs.fo.xx = 'xxxxxx' // 在父组件中修改子组件属性
}
// 子组件
...

d. 子元素 $children

$parent用法差不多
// 父组件
created () {
    this.$children[0].xx = 'xxxxxx' // 子元素不保证顺序
}

2. 子组件 => 父组件

自定义事件

// 子组件
this.$emit('add', foo)
// 父组件
<Cart $add="cartAdd($event)"></Cart>
methods: {
    cartAdd(data) {console.log('获取到子组件传递过来的数据:', data)}
}

3. 兄弟组件:通过共同祖辈组件parent或root

// 兄弟1
this.$parent.$on('foo', function() {...})
// 兄弟2
this.$parent.$emit('foo', 'foo')

4. 祖先与后代之间 provide/inject

由于嵌套层数过多,传递props不实际,vue提供了 provide/inject API完成该任务

// 祖先元素
provide() {
    return {foo: 'xxxxx'}
}
// 子元素
inject: ['foo']

5. 任意两个组件之间

事件总线或vuex

// bus.js  创建一个bus类,负责事件的派发和监听,回调管理
class bus {
    constructor() {
        this.callbacks = {}
    }
    $on(name, fn) {
        this.callbacks[name] = this.callbacks[name] || []
        this.callbacks[name].push(fn)
    }
    $emit(name, args) {
        this.callbacks[name].forEach(f => f(args))
    }
}

// main.js
import Bus from './bus'
Vue.prototype.$bus = new Bus()
// comporent1
this.$bus.$on('func', function() {...})
// comporent2
this.$bus.$emit('func', 'fo')

实践中可以用Vue代替Bus,因为它已经实现了相应功能

6. vuex: 创建唯一的全局数据管理者store,通过它管理数据并通知组件状态变更