组件间通信方式有哪些

Youky ... 2021-8-30 前端
  • Vue
About 2 min

# 组件间通信方式有哪些

# 1. 最常用方式,props:父子组件

  • 父组件用props向子组件传值
  • 子组件用$emit触发自定义事件,向父组件传值

# 2. 通过 ref、$parent$children:父子组件

ref用来便捷的访问某个节点或是自定义组件。

ref 只会在组件渲染完成后生效,并且不是响应式的

  • 用在 DOM 节点上时和 ID 类似
  • 用在组件上时获取的是这个 Vue 实例
  • ref 与 v-for 一起使用时,得到的是包含了所有子组件的数组
<myCom ref="myInput" />
1
// 获取这个组件,类似于获得了它的this指针
this.$refs.myInput;
1
2

$parent用于获得组件的父组件,可以获取其数据或调用其方法。

$children用于获得组件的子组件。在 vue3 中已移除,需要时用 ref 作为代替

# 3. 依赖注入:隔代组件

使用方法:

  • 在父组件使用provide属性,向所有子组件(不只是直接子组件,包括深层嵌套的子组件)提供值
  • 在子组件中用 inject 属性进行接收

缺点:

  • 是非响应式的。
  • 使组件和组织方式耦合起来,不利于重构
// 父组件
{
  // ...
  provide(){
    return{
      name: this.name
    }
  }
}

// 所有子组件或子组件的子组件中都可以接收:
{
  inject:['name']
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

如何解决非响应式的问题?

  1. 传递一个函数或是直接传递 this
provide() { return { parent: this } }
1
provide() {
  return {
    parentName: () => this.name
  }
}
1
2
3
4
5
  1. Vue3 中使用 computed 包裹传递内容
import { computed } from "vue";
export default {
  data() {
    return {
      message: "hello!",
    };
  },
  provide() {
    return {
      // 显式提供一个计算属性
      message: computed(() => this.message),
    };
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 4. $attrs/$listeners:隔代组件

  • $attrs:包含了父组件传递了但没有在 props 中进行接收的 props(class 和 style 除外)
<children v-bind="$attrs"></children>
1
  • $listeners:包含了父级作用域中的 v-on 监听器
<children v-on="$listeners"></children>
1

# 5. 总线模式/发布订阅模式:全局可用,低配版 Vuex

  1. 用一个空的 Vue 实例作为中心事件总线,用它来监听和触发事件,从而实现组件间通信。
// $bus为事件总线的名称,自己随意定义
Vue.prototype.$bus = new Vue();

new Vue({}).$mount("#app");
1
2
3
4
  1. 在需要传递信息的地方触发自定义事件
this.$bus.$emit("事件名", "事件参数");
1
  1. 在需要接收的地方监听事件
this.$bus.$on("事件名", (arg) => {});
1

总线模式的缺点:

  • vue 是 SPA,在某个页面刷新后,与之相关的 eventbus 会被移除
  • 不利于组件化开发

# 6. 终极方案:Vuex

Last update: October 16, 2022 21:28
Contributors: youky7 , Youky