vue组件通讯7种方式

props/@on+$emit

用于实现父子组件间通信。通过 props 可以把父组件的消息传递给子组件:

// parent.vue    
<child :title="title"></child>
// child.vue
props: {
    title: {
        type: String,
        default: '',
    }
}

这样一来 this.title 就直接拿到从父组件中传过来的 title 的值了。注意,你不应该在子组件内部直接改变 prop,这里就不多赘述,可以直接看官网介绍。

而通过 @on+$emit 组合可以实现子组件给父组件传递信息:

// parent.vue
<child @changeTitle="changeTitle"></child>
// child.vue
this.$emit('changeTitle', 'bubuzou.com')

attr和listeners

Vue_2.4 中新增的 $attrs/$listeners 可以进行跨级的组件通信。$attrs 包含了父级作用域中不作为 prop 的属性绑定(class 和 style 除外),好像听起来有些不好理解?没事,看下代码就知道是什么意思了:

 

// 父组件 index.vue
<list class="list-box" title="标题" desc="描述" :list="list"></list>
// 子组件 list.vue
props: {
    list: [],
},
mounted() {
    console.log(this.$attrs)  // {title: "标题", desc: "描述"}
}

在上面的父组件 index.vue 中我们给子组件 list.vue 传递了4个参数,但是在子组件内部 props 里只定义了一个 list,那么此时 this.$attrs 的值是什么呢?首先要去除 props 中已经绑定了的,然后再去除 class 和 style,最后剩下 title 和 desc 结果和打印的是一致的。基于上面代码的基础上,我们在给 list.vue 中加一个子组件:

// 子组件 list.vue
<detail v-bind="$attrs"></detial>
// 孙子组件 detail.vue
// 不定义props,直接打印 $attrs
mounted() {
    console.log(this.$attrs)  // {title: "标题", desc: "描述"}
}

在子组件中我们定义了一个 v-bind="$attrs" 可以把父级传过来的参数,去除 propsclass 和 style 之后剩下的继续往下级传递,这样就实现了跨级的组件通信。

$attrs 是可以进行跨级的参数传递,实现父到子的通信;同样的,通过 $listeners 用类似的操作方式可以进行跨级的事件传递,实现子到父的通信。$listeners 包含了父作用域中不含 .native 修饰的 v-on 事件监听器,通过 v-on="$listeners" 传递到子组件内部。

// 父组件 index.vue
<list @change="change" @update.native="update"></list>

// 子组件 list.vue
<detail v-on="$listeners"></detail>
// 孙子组件 detail.vue
mounted() {
    this.$listeners.change()
    this.$listeners.update() // TypeError: this.$listeners.update is not a function
}

provide/inject组合拳

provide/inject 组合以允许一个祖先组件向其所有子孙后代注入一个依赖,可以注入属性和方法,从而实现跨级父子组件通信。在开发高阶组件和组件库的时候尤其好用。
上一篇:~~番外:说说Python 面向对象编程~~


下一篇:Android自定义TextView