MST

星途 面试题库

面试题:复杂业务下Vue条件渲染与列表渲染的架构设计

假设你正在开发一个大型企业级项目,其中涉及到多层次嵌套的列表渲染,并且每个列表项都需要根据不同的用户角色、权限以及业务状态进行复杂的条件渲染。请阐述你会如何设计Vue组件结构和数据管理方式,以确保代码的可维护性、性能以及扩展性。
18.9万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

1. Vue 组件结构设计

  • 基础列表组件
    • 创建一个基础的列表组件,例如 BaseList.vue。此组件负责接收父组件传递的数据列表,并进行基本的列表渲染。它只处理列表的基本展示逻辑,如循环渲染列表项,不涉及复杂的条件判断。
    <template>
      <ul>
        <li v - for="(item, index) in list" :key="index">{{ item }}</li>
      </ul>
    </template>
    
    <script>
    export default {
      props: {
        list: {
          type: Array,
          default: () => []
        }
      }
    };
    </script>
    
  • 列表项组件
    • 针对每个列表项,创建 ListItem.vue 组件。该组件接收来自父组件传递的单个列表项数据、用户角色、权限以及业务状态等信息。在组件内部,通过 computed 计算属性和 v - ifv - show 指令来实现复杂的条件渲染。
    <template>
      <div>
        <span v - if="shouldShowContent1">{{ item.content1 }}</span>
        <span v - if="shouldShowContent2">{{ item.content2 }}</span>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        item: {
          type: Object,
          required: true
        },
        userRole: {
          type: String,
          required: true
        },
        userPermissions: {
          type: Array,
          default: () => []
        },
        businessStatus: {
          type: String,
          required: true
        }
      },
      computed: {
        shouldShowContent1() {
          // 根据用户角色、权限和业务状态进行判断
          return this.userRole === 'admin' && this.userPermissions.includes('viewContent1') && this.businessStatus === 'active';
        },
        shouldShowContent2() {
          // 另一种复杂条件判断
          return this.userRole === 'user' && this.businessStatus === 'completed';
        }
      }
    };
    </script>
    
  • 嵌套列表组件
    • 对于多层次嵌套的列表,创建 NestedList.vue 组件。它继承自 BaseList.vue,但在列表项渲染时,对于具有子列表的项,递归调用自身来渲染子列表。
    <template>
      <ul>
        <li v - for="(item, index) in list" :key="index">
          <ListItem :item="item" :user - role="userRole" :user - permissions="userPermissions" :business - status="businessStatus" />
          <NestedList v - if="item.children && item.children.length > 0" :list="item.children" :user - role="userRole" :user - permissions="userPermissions" :business - status="businessStatus" />
        </li>
      </ul>
    </template>
    
    <script>
    import ListItem from './ListItem.vue';
    import NestedList from './NestedList.vue';
    
    export default {
      components: {
        ListItem,
        NestedList
      },
      props: {
        list: {
          type: Array,
          default: () => []
        },
        userRole: {
          type: String,
          required: true
        },
        userPermissions: {
          type: Array,
          default: () => []
        },
        businessStatus: {
          type: String,
          required: true
        }
      }
    };
    </script>
    

2. 数据管理方式

  • Vuex
    • 状态管理:使用 Vuex 来管理全局状态,如用户角色、权限等。将用户角色和权限存储在 Vuex 的 state 中,通过 mutations 来修改状态,确保状态的一致性和可追溯性。
    // store.js
    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    const store = new Vuex.Store({
      state: {
        userRole: null,
        userPermissions: []
      },
      mutations: {
        SET_USER_ROLE(state, role) {
          state.userRole = role;
        },
        SET_USER_PERMISSIONS(state, permissions) {
          state.userPermissions = permissions;
        }
      },
      actions: {
        setUserRole({ commit }, role) {
          commit('SET_USER_ROLE', role);
        },
        setUserPermissions({ commit }, permissions) {
          commit('SET_USER_PERMISSIONS', permissions);
        }
      }
    });
    
    export default store;
    
    • 模块划分:对于大型项目,可以将 Vuex 按照业务模块进行划分,每个模块管理自己相关的状态、mutation 和 action。例如,创建一个 businessModule 来管理业务状态相关的状态和逻辑。
    // businessModule.js
    const businessModule = {
      namespaced: true,
      state: {
        businessStatus: 'initial'
      },
      mutations: {
        SET_BUSINESS_STATUS(state, status) {
          state.businessStatus = status;
        }
      },
      actions: {
        setBusinessStatus({ commit }, status) {
          commit('SET_BUSINESS_STATUS', status);
        }
      }
    };
    
    export default businessModule;
    
    • 组件使用:在组件中通过 mapStatemapActions 辅助函数来获取 Vuex 中的状态和调用 action。
    <template>
      <div>
        <!-- 列表渲染 -->
      </div>
    </template>
    
    <script>
    import { mapState, mapActions } from 'vuex';
    
    export default {
      computed: {
      ...mapState(['userRole', 'userPermissions']),
      ...mapState('businessModule', ['businessStatus'])
      },
      methods: {
      ...mapActions(['setUserRole','setUserPermissions']),
      ...mapActions('businessModule', ['setBusinessStatus'])
      }
    };
    </script>
    
  • 本地数据
    • 对于每个列表项组件内部的一些临时状态,可以使用组件自身的 data 选项来管理。例如,列表项的展开/折叠状态等与单个列表项紧密相关的状态。
    <template>
      <div>
        <button @click="toggleExpand">{{ isExpanded? 'Collapse' : 'Expand' }}</button>
        <div v - if="isExpanded">
          <!-- 展开内容 -->
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          isExpanded: false
        };
      },
      methods: {
        toggleExpand() {
          this.isExpanded =!this.isExpanded;
        }
      }
    };
    </script>
    

3. 性能优化

  • 虚拟 DOM 与 diff 算法:Vue 本身基于虚拟 DOM 和 diff 算法,会高效地更新实际 DOM。在列表渲染中,确保为每个列表项提供唯一的 key 值,这有助于 Vue 更准确地识别变化,提高更新效率。
  • 防抖与节流:如果在条件渲染过程中涉及到频繁的用户交互(如切换用户角色、权限等),可以使用防抖或节流技术。例如,使用 lodashdebouncethrottle 函数来限制状态更新的频率,避免不必要的重新渲染。
    <template>
      <select @change="debouncedChangeRole">
        <option value="admin">Admin</option>
        <option value="user">User</option>
      </select>
    </template>
    
    <script>
    import { debounce } from 'lodash';
    import { mapActions } from 'vuex';
    
    export default {
      methods: {
      ...mapActions(['setUserRole']),
        changeRole(role) {
          this.setUserRole(role);
        },
        debouncedChangeRole: debounce(function (e) {
          this.changeRole(e.target.value);
        }, 300)
      }
    };
    </script>
    
  • 异步加载:对于大型列表数据,考虑采用异步加载策略。例如,使用 vue - lazyload 等插件来实现列表数据的按需加载,避免一次性加载大量数据导致性能问题。同时,在多层次嵌套列表中,也可以异步加载子列表数据,只有在用户展开父列表项时才加载子列表。

4. 扩展性

  • 组件复用:通过上述组件结构设计,基础列表组件、列表项组件和嵌套列表组件都具有较高的复用性。当项目中其他地方需要类似的多层次嵌套列表渲染时,可以直接复用这些组件,只需传入不同的数据和状态即可。
  • 新条件扩展:如果后续有新的用户角色、权限或业务状态需要加入条件渲染逻辑,在 ListItem.vue 组件的 computed 计算属性中添加新的判断逻辑即可。同时,在 Vuex 中相应地扩展状态管理,例如添加新的权限字段等。
  • 功能模块扩展:如果项目需要增加新的功能模块,如对列表项进行排序、筛选等功能,可以在现有组件基础上进行扩展。例如,创建新的 ListSort.vueListFilter.vue 组件,通过传递事件和数据来与原有的列表组件协同工作,实现功能的扩展。