Логическое повторное использование и оптимизация производительности

После завершения логики маршрутизации и входа, по мере масштабирования проекта, мы обнаружим, что некоторая логика (например, доступ к локальным данным, всплывающие уведомления) повторяется на нескольких страницах. В то же время, если список задач достигает тысяч элементов, страница может тормозить.

На этом этапе мы будем использоватьглубокое применение Composition APIдля решения проблем повторного использования кода и узких мест производительности.


Повторное использование логики: Пользовательские композаблы (хуки)

Композаблы — это суть Vue 3; они позволяют нам выносить логику (State + Actions) в независимые функции.

useLocalStorage: Извлечение логики сохранения данных

Больше не нужно вручную писать в каждом хранилище или компонентеlocalStorage.getItem。

Пример

// src/composables/useLocalStorage.js
import { ref, watch } from 'vue';

export function useLocalStorage(key, defaultValue = null) {
  // 1. Инициализация данных
  const storedValue = localStorage.getItem(key);
  const data = ref(storedValue ? JSON.parse(storedValue) : defaultValue);

  // 2. Отслеживание изменений и автоматическая синхронизация
  watch(data, (newValue) => {
    localStorage.setItem(key, JSON.stringify(newValue));
  }, { deep: true });

  return data;
}

useNotification: Извлечение общей логики UI

Реализуйте простую функцию уведомления.

Пример

// src/composables/useNotification.js
import { ref } from 'vue';

export function useNotification() {
  const message = ref('');
  const isVisible = ref(false);

  const notify = (msg, duration = 2000) => {
    message.value = msg;
    isVisible.value = true;
    setTimeout(() => {
      isVisible.value = false;
    }, duration);
  };

  return { message, isVisible, notify };
}

Оптимизация производительности: обработка больших объёмов данных и высокочастотного рендеринга

Когда ваш TaskHub вырастает с управления 10 задачами до управления 1000 задачами, стандартная "глубокая реактивность" Vue будет создавать вычислительную нагрузку.

shallowRefиmarkRaw

Стандартное поведение Vuerefявляется рекурсивно реактивным (т. е. каждое свойство внутри объекта проксируется).

shallowRef: Отслеживать только.valueизменение ссылки, а не изменения внутренних свойств объекта.

  • Сценарий: Когда вы получаете с бэкенда большой список истории задач, доступный только для чтения.

markRaw: Пометить объект, чтобы онникогдане преобразовывался в реактивный.

  • Сценарий: Некоторые сложные экземпляры сторонних библиотек (например, экземпляры диаграмм ECharts, экземпляры карт) могут вызывать ошибки или быть чрезвычайно ресурсоёмкими, если обернуть их в реактивность.
// 性能优化示例
import { shallowRef, markRaw } from 'vue';

// 假设这是一万条历史归档数据
const archiveTasks = shallowRef([]); 

const loadArchive = (data) => {
  // 仅在赋值时触发一次响应式更新,内部属性修改不触发
  archiveTasks.value = data; 
};

v-onceиv-memo(Оптимизация на уровне директив)

v-once: Статическое содержимое рендерится только один раз

Если задача больше не изменяется после рендеринга (например, время создания задачи), используйтеv-once。

<span v-once>创建于: {{ task.createdAt }}</span>
  • Принцип: После рендеринга Vue пропускает последующие проверки обновления для этого узла.

v-memo: Обновление по требованию (Vue 3.2+)

Это самая мощная директива для оптимизации длинных списков. Она принимает массив зависимостей; только когда значения в массиве изменяются, узел и его дочерние узлы будут повторно рендериться.

<li v-for="task in tasks" :key="task.id" v-memo="[task.isCompleted, task.title]">
  {{ task.title }} - {{ task.isCompleted }}
</li>

Когда стоит оптимизировать?

Решение Решаемые проблемы Рекомендуемые сценарии
Composables Дублирование кода, разрозненная логика Общая логика между компонентами (например, проверки входа, переключение темы)
shallowRef Накладные расходы памяти из-за глубокого проксирования больших объектов Когда объём данных списка > 1000 и требуется только полная замена
v-memo Частый diffing виртуального DOM для длинных списков Сложныеv-forсписки, и у каждого элемента меняется лишь несколько свойств

Интеграция в предыдущий проект

Вы можете попробоватьTaskItem.vueприменить вv-memo:

<template>
  <li v-memo="[task.id, task.isCompleted]" class="...">
     ...
  </li>
</template>

Теперь ваш проект не только логически понятен (Composables), но и обладает высокой производительностью.

Другие расширения