MST

星途 面试题库

面试题:Vue Composition API下如何实现深度解耦设计并优化模块间通信

假设在一个大型Vue项目中,有多个相互关联但又需要解耦的模块,如商品模块、购物车模块和订单模块。使用Vue Composition API,如何实现这些模块的深度解耦,同时有效处理模块间的通信,例如购物车添加商品后,订单模块实时更新总价。请详细说明设计思路及关键代码实现。
10.9万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用Provide/Inject 实现跨组件通信:通过provide在父组件中提供数据或方法,子组件通过inject来获取,适用于深度嵌套组件间通信。
  2. 使用自定义事件总线:创建一个独立的Vue实例作为事件总线,模块间通过事件总线来触发和监听事件,实现通信。
  3. 状态管理:利用Vuex来管理共享状态,各个模块都可以从Vuex中获取和修改状态,达到解耦通信目的。

关键代码实现

Provide/Inject

  1. 商品模块
<template>
  <div>
    <button @click="addToCart(product)">添加到购物车</button>
  </div>
</template>

<script setup>
import { provide } from 'vue';
import { ref } from 'vue';

const product = ref({ name: '示例商品', price: 10 });

const addToCart = (product) => {
  // 这里逻辑可实际将商品添加到购物车逻辑
  console.log(`将 ${product.name} 添加到购物车`);
};

provide('product', product);
provide('addToCart', addToCart);
</script>
  1. 购物车模块
<template>
  <div>
    <div v-for="item in cartItems" :key="item.name">{{ item.name }} - {{ item.price }}</div>
  </div>
</template>

<script setup>
import { inject } from 'vue';

const product = inject('product');
const addToCart = inject('addToCart');

const cartItems = [];

// 这里假设购物车添加逻辑
if (product.value && addToCart) {
  cartItems.push(product.value);
}
</script>
  1. 订单模块
<template>
  <div>
    <p>订单总价: {{ totalPrice }}</p>
  </div>
</template>

<script setup>
import { inject } from 'vue';

const cartItems = inject('cartItems');

const totalPrice = computed(() => {
  return cartItems.reduce((acc, item) => acc + item.price, 0);
});
</script>

自定义事件总线

  1. 创建事件总线
import { createApp } from 'vue';
const eventBus = createApp({}).config.globalProperties.$eventBus = new Vue();
export default eventBus;
  1. 商品模块
<template>
  <div>
    <button @click="addToCart(product)">添加到购物车</button>
  </div>
</template>

<script setup>
import eventBus from './eventBus';
import { ref } from 'vue';

const product = ref({ name: '示例商品', price: 10 });

const addToCart = (product) => {
  eventBus.$emit('productAdded', product);
  console.log(`将 ${product.name} 添加到购物车`);
};
</script>
  1. 购物车模块
<template>
  <div>
    <div v-for="item in cartItems" :key="item.name">{{ item.name }} - {{ item.price }}</div>
  </div>
</template>

<script setup>
import eventBus from './eventBus';
import { ref } from 'vue';

const cartItems = ref([]);

eventBus.$on('productAdded', (product) => {
  cartItems.value.push(product);
  eventBus.$emit('cartUpdated', cartItems.value);
});
</script>
  1. 订单模块
<template>
  <div>
    <p>订单总价: {{ totalPrice }}</p>
  </div>
</template>

<script setup>
import eventBus from './eventBus';
import { ref, computed } from 'vue';

const cartItems = ref([]);
const totalPrice = computed(() => {
  return cartItems.value.reduce((acc, item) => acc + item.price, 0);
});

eventBus.$on('cartUpdated', (items) => {
  cartItems.value = items;
});
</script>

Vuex

  1. 安装并配置Vuex
import { createStore } from 'vuex';

const store = createStore({
  state() {
    return {
      cartItems: [],
    };
  },
  mutations: {
    addProductToCart(state, product) {
      state.cartItems.push(product);
    },
  },
  getters: {
    totalPrice(state) {
      return state.cartItems.reduce((acc, item) => acc + item.price, 0);
    },
  },
});

export default store;
  1. 商品模块
<template>
  <div>
    <button @click="addToCart(product)">添加到购物车</button>
  </div>
</template>

<script setup>
import { useStore } from 'vuex';
import { ref } from 'vue';

const product = ref({ name: '示例商品', price: 10 });
const store = useStore();

const addToCart = (product) => {
  store.commit('addProductToCart', product);
  console.log(`将 ${product.name} 添加到购物车`);
};
</script>
  1. 订单模块
<template>
  <div>
    <p>订单总价: {{ totalPrice }}</p>
  </div>
</template>

<script setup>
import { useStore } from 'vuex';

const store = useStore();
const totalPrice = computed(() => store.getters.totalPrice);
</script>