Логическое повторное использование и оптимизация производительности
После завершения логики маршрутизации и входа, по мере масштабирования проекта, мы обнаружим, что некоторая логика (например, доступ к локальным данным, всплывающие уведомления) повторяется на нескольких страницах. В то же время, если список задач достигает тысяч элементов, страница может тормозить.
На этом этапе мы будем использоватьглубокое применение Composition APIдля решения проблем повторного использования кода и узких мест производительности.
Повторное использование логики: Пользовательские композаблы (хуки)
Композаблы — это суть Vue 3; они позволяют нам выносить логику (State + Actions) в независимые функции.
useLocalStorage: Извлечение логики сохранения данных
Больше не нужно вручную писать в каждом хранилище или компонентеlocalStorage.getItem。
Пример
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
Реализуйте простую функцию уведомления.
Пример
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), но и обладает высокой производительностью.
Другие расширения