MST

星途 面试题库

面试题:Vue Composition API在实际项目中如何优化列表渲染性能

在使用Vue Composition API开发列表相关功能时,数据量较大可能导致性能问题。请阐述你会采取哪些措施来优化列表渲染性能,例如从数据处理、指令使用、组件设计等方面说明,并结合Vue Composition API的特性,如reactive、computed等。
28.9万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

数据处理

  1. 分页
    • 使用reactive定义当前页码和每页显示数量。例如:
import { reactive } from 'vue';
const state = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
  dataList: []
});
- 根据当前页码和每页数量从原始大数据集中截取需要展示的数据。可以使用`computed`计算属性:
import { reactive, computed } from 'vue';
const state = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
  allData: []
});
const displayedData = computed(() => {
  const start = (state.currentPage - 1) * state.pageSize;
  const end = start + state.pageSize;
  return state.allData.slice(start, end);
});
  1. 虚拟列表
    • 借助@vueuse/core库中的useVirtualList等工具实现虚拟列表。在数据处理时,只渲染可见区域的数据。例如:
import { useVirtualList } from '@vueuse/core';
import { reactive } from 'vue';
const state = reactive({
  largeData: Array.from({ length: 10000 }, (_, i) => i + 1)
});
const { items, scrollTo } = useVirtualList(state.largeData, {
  height: 200,
  itemHeight: 30
});

指令使用

  1. v - for 优化
    • v - for绑定的列表项提供唯一的key值。这有助于Vue更高效地更新DOM。例如:
<template>
  <div v - for="(item, index) in displayedData" :key="item.id">
    {{ item.name }}
  </div>
</template>
  1. 避免不必要的指令
    • 减少在列表项模板中使用会频繁触发重新渲染的指令,如v - if。如果需要根据条件显示或隐藏列表项,可以在数据处理阶段过滤数据,而不是在模板中使用v - if

组件设计

  1. 列表项组件化
    • 将列表项封装成单独的组件,提高代码复用性和可维护性。同时可以对列表项组件进行keep - alive缓存,减少重复渲染。例如:
<template>
  <div>
    <ListItem v - for="(item, index) in displayedData" :key="item.id" :data="item" />
  </div>
</template>
<script setup>
import ListItem from './ListItem.vue';
</script>
  1. 懒加载
    • 对于图片等资源,可以在列表项组件中实现懒加载。可以使用IntersectionObserver结合reactive数据来控制图片的加载时机。例如,在列表项组件中:
import { reactive, onMounted } from 'vue';
export default {
  setup() {
    const state = reactive({
      isLoaded: false
    });
    onMounted(() => {
      const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            state.isLoaded = true;
            observer.unobserve(entry.target);
          }
        });
      });
      const imgEl = document.getElementById('list - item - img');
      if (imgEl) {
        observer.observe(imgEl);
      }
    });
    return {
      state
    };
  }
};
<template>
  <div>
    <img v - if="state.isLoaded" :src="item.imgUrl" />
    <img v - else src="placeholder.jpg" />
  </div>
</template>