MST

星途 面试题库

面试题:Vue Composition API在大型项目架构及性能优化场景的应用

在一个大型企业级Vue项目中,涉及到多模块、多视图的复杂业务。请基于Vue Composition API设计一套通用的项目架构,包括如何进行模块划分、状态管理、性能优化(如代码分割、懒加载等)。并阐述在实际开发过程中,如何通过Composition API来解决大型项目中可能出现的代码耦合、可维护性差等问题。
49.6万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

模块划分

  1. 功能模块划分:根据业务功能将项目划分为独立的模块,例如用户模块、订单模块、商品模块等。每个模块包含自己的组件、逻辑和路由。
  2. 目录结构
src/
├── modules/
│   ├── user/
│   │   ├── components/
│   │   │   ├── UserLogin.vue
│   │   │   ├── UserRegister.vue
│   │   ├── services/
│   │   │   ├── userApi.js
│   │   ├── stores/
│   │   │   ├── userStore.js
│   │   ├── userRoutes.js
│   │   ├── userModule.js
│   ├── order/
│   │   ├──...
├── App.vue
├── main.js
  1. 模块化导出:在每个模块的 userModule.js 中,使用 export 导出模块相关的配置、函数等,便于在其他地方引用。

状态管理

  1. 使用 Vuex 结合 Composition API
    • 创建 store 文件夹,在每个模块的 stores 目录下创建各自的状态管理文件,如 userStore.js
    • userStore.js 中使用 createStore 函数创建 Vuex 模块。
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
    state: () => ({
        userInfo: null,
        token: ''
    }),
    actions: {
        async login(userData) {
            // 调用登录接口
            const response = await userApi.login(userData);
            this.userInfo = response.data.user;
            this.token = response.data.token;
        }
    }
});
  1. 在组件中使用:在组件中通过 useUserStore 函数获取状态和调用方法。
<template>
    <button @click="login">登录</button>
</template>

<script setup>
import { useUserStore } from '@/modules/user/stores/userStore';

const userStore = useUserStore();
const login = () => {
    userStore.login({ username: 'test', password: '123456' });
};
</script>

性能优化

  1. 代码分割
    • 使用 import() 动态导入组件。例如在路由配置中:
const routes = [
    {
        path: '/user/login',
        name: 'UserLogin',
        component: () => import('@/modules/user/components/UserLogin.vue')
    }
];
  1. 懒加载
    • 对于图片等资源,可以使用 loading="lazy" 属性实现浏览器原生的懒加载。
    • 对于组件,除了上述路由的动态导入实现懒加载,还可以在父组件中使用 v-if 结合 refnextTick 实现条件懒加载。
<template>
    <div>
        <button @click="loadComponent">加载组件</button>
        <component v-if="isComponentLoaded" :is="loadedComponent"></component>
    </div>
</template>

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

const isComponentLoaded = ref(false);
const loadedComponent = ref(null);

const loadComponent = async () => {
    await nextTick();
    loadedComponent.value = await import('@/modules/user/components/UserInfo.vue');
    isComponentLoaded.value = true;
};
</script>

解决代码耦合和可维护性问题

  1. 逻辑复用:通过 setup 函数将相关逻辑封装成可复用的函数。例如在多个组件中都需要获取用户信息,可以创建一个 useUserInfo 函数。
import { ref, onMounted } from 'vue';
import { useUserStore } from '@/modules/user/stores/userStore';

export const useUserInfo = () => {
    const userInfo = ref(null);
    const userStore = useUserStore();

    onMounted(() => {
        userInfo.value = userStore.userInfo;
    });

    return { userInfo };
};

在组件中使用:

<template>
    <div>
        <p>{{ userInfo }}</p>
    </div>
</template>

<script setup>
import { useUserInfo } from '@/modules/user/useUserInfo';

const { userInfo } = useUserInfo();
</script>
  1. 清晰的代码结构setup 函数内按照功能划分代码块,如数据定义、生命周期钩子、方法定义等,使代码结构清晰,易于维护。
  2. 依赖管理:在 setup 函数参数中明确声明依赖,通过解构获取依赖,提高代码的可理解性和可维护性。例如:
import { ref, computed, inject } from 'vue';

export default {
    setup(props, { attrs, slots, emit }) {
        const parentValue = inject('parentValue');
        const localData = ref('');
        const computedValue = computed(() => localData.value + parentValue);

        const handleClick = () => {
            emit('customEvent', computedValue.value);
        };

        return { localData, computedValue, handleClick };
    }
};