vue2、vue3多组件通信方案(简单介绍)

Vue2/Vue3多组件通信方案

一般的话,主要使用这6种:

  1. 事件总线/Event Emitter模式(Vue2/3)

  2. Vuex状态管理(Vue2)

  3. Pinia状态管理(Vue3)

  4. Provide/Inject依赖注入(Vue2/3)

  5. 组合式函数(Composables)(vue3)

下面将简单介绍及使用:

1. 事件总线/Event Emitter模式

事件总线是一种发布/订阅模式,允许组件之间进行通信。

Vue2 实现
// event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();

// ComponentA.vue (发送事件)
<script>
import { EventBus } from './event-bus';

export default {
  methods: {
    sendMessage() {
      EventBus.$emit('message-sent', this.message);
    }
  }
};
</script>

// ComponentB.vue (接收事件)
<script>
import { EventBus } from './event-bus';

export default {
  created() {
    EventBus.$on('message-sent', this.handleMessage);
  },
  beforeDestroy() {
    EventBus.$off('message-sent', this.handleMessage);
  },
  methods: {
    handleMessage(message) {
      console.log(message);
    }
  }
};
</script>
Vue3 实现

由于Vue3不再有实例事件机制,需要自己实现一个事件总线,或者使用npm下包,比如mitt等等,详细见这里:如需了解请点此处

// event-bus.js
export const EventBus = {
  events: {},
  $on(event, callback) {
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(callback);
  },
  $emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(data));
    }
  },
  $off(event, callback) {
    if (!this.events[event]) return;
    if (!callback) {
      delete this.events[event];
    } else {
      this.events[event] = this.events[event].filter(cb => cb !== callback);
    }
  }
};

/使用方式与Vue2类似,只是不需要导入Vue,而是导入这个自定义的EventBus

属性

  • $on(event, callback): 监听事件,当事件被触发时执行回调。

  • $emit(event, data): 触发事件,可传递数据。

  • $off(event, callback): 移除事件监听器。

注意事项

  • 事件总线是全局的,容易导致事件冲突,建议给事件名加上命名空间。

  • 在组件销毁前务必移除事件监听,避免内存泄漏。

  • 不适合大型复杂项目,因为事件流会变得难以追踪。

2. Vuex状态管理(Vue2)

使用方法

Vuex是Vue官方状态管理库,适用于中大型项目。

安装与配置
npm install vuex
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment');
      }, 1000);
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
});

// main.js
import store from './store';

new Vue({
  store,
  // ...其他配置
}).$mount('#app');
在组件中使用
// Component.vue
<script>
export default {
  computed: {
    count() {
      return this.$store.state.count;
    },
    doubleCount() {
      return this.$store.getters.doubleCount;
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment');
    },
    incrementAsync() {
      this.$store.dispatch('incrementAsync');
    }
  }
};
</script>

5个核心属性:

  • state: 存储应用状态的数据对象。

  • mutations: 更改state的唯一方法,必须是同步函数。

  • actions: 提交mutation,可以包含异步操作。

  • getters: 基于state的计算属性。

注意事项

  • 不要直接修改state,必须通过commit mutation来修改。

  • 使用mapState、mapGetters、mapMutations、mapActions辅助函数来简化代码。

  • 模块化:当状态多的时候,可以将store分割成模块。

3. Pinia状态管理(Vue3)

使用方法

Pinia是Vue3推荐的状态管理库,比Vuex更简洁。

安装与配置
npm install pinia
// stores/counter.js
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      this.count++;
    },
    async incrementAsync() {
      setTimeout(() => {
        this.increment();
      }, 1000);
    }
  },
  getters: {
    doubleCount: (state) => state.count * 2
  }
});

// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';

const pinia = createPinia();
createApp(App).use(pinia).mount('#app');
在组件中使用
<script>
import { useCounterStore } from '@/stores/counter';

export default {
  setup() {
    const counterStore = useCounterStore();

    return {
      count: counterStore.count,
      doubleCount: counterStore.doubleCount,
      increment: counterStore.increment,
      incrementAsync: counterStore.incrementAsync
    };
  }
};
</script>

3个核心属性

  • state: 存储状态。

  • actions: 可以是同步或异步,直接修改state。

  • getters: 计算属性。

注意事项

  • Pinia没有mutations,actions直接修改state。

  • 支持TypeScript,提供更好的类型推断。

  • 支持模块化,每个store都是一个独立的模块。

4. Provide/Inject依赖注入

使用方法

祖先组件提供数据,后代组件注入数据。

Vue2 实现
// 祖先组件
<script>
export default {
  provide() {
    return {
      message: this.message
    };
  },
  data() {
    return {
      message: 'Hello from ancestor'
    };
  }
};
</script>

// 后代组件
<script>
export default {
  inject: ['message']
};
</script>
Vue3 实现
// 祖先组件
<script>
import { provide, ref } from 'vue';

export default {
  setup() {
    const message = ref('Hello from ancestor');
    provide('message', message);

    return { message };
  }
};
</script>

// 后代组件
<script>
import { inject } from 'vue';

export default {
  setup() {
    const message = inject('message');

    return { message };
  }
};
</script>

注意

  • 提供的数据不是响应式的(Vue2中),如果需要响应式,可以提供父组件的实例或使用observable。

  • 在Vue3中,使用ref或reactive提供响应式数据。

  • 主要用于开发高阶插件/组件库,普通应用慎用,因为会导致组件间耦合。

5. 组合式函数(Composables)

使用方法

组合式函数是Vue3的特性,用于封装可复用的逻辑。

示例

javascript

// useCounter.js
import { ref, computed } from 'vue';

export function useCounter() {
  const count = ref(0);
  const doubleCount = computed(() => count.value * 2);

  function increment() {
    count.value++;
  }

  return { count, doubleCount, increment };
}

// 在组件中使用
<script>
import { useCounter } from './useCounter';

export default {
  setup() {
    const { count, doubleCount, increment } = useCounter();

    return { count, doubleCount, increment };
  }
};
</script>

注意事项

  • 组合式函数命名通常以use开头。

  • 可以在组合式函数内部使用其他组合式函数,实现逻辑组合。

  • 适合提取可复用的逻辑,使组件更简洁。

最后:

  • 事件总线:简单场景,非父子组件通信,但容易导致混乱。

  • Vuex:Vue2中大型项目状态管理。

  • Pinia:Vue3推荐的状态管理,API更简洁。

  • Provide/Inject:深层嵌套组件通信,但耦合性高。

  • 组合式函数:Vue3逻辑复用,提高代码可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

じòぴé南冸じょうげん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值