Мемоизация и лишние ре-рендеры
↑ 7.2 Рендеринг и производительность · ← Предыдущая · → Следующая
Зачем это на собесе
Вопрос на понимание, что вызывает рендер и как остановить лишнюю работу без преждевременной оптимизации.
Что вызывает рендер компонента во Vue
- изменение реактивных данных, использованных в шаблоне;
- изменение props;
- принудительное обновление (редко).
Vue отслеживает зависимости точно: изменение неиспользуемого свойства рендер не вызывает.
Инструменты
| Инструмент | Назначение |
|---|---|
computed | кэш производных данных, пересчёт при смене зависимостей |
v-memo | пропуск патчинга поддерева |
v-once | единоразовый рендер |
shallowRef | реактивна только замена |
KeepAlive | сохраняет состояние неактивных компонентов |
defineAsyncComponent | отложенная загрузка |
Типичные причины лишних рендеров
- новые объекты и функции в props при каждом рендере родителя (в Vue дочерний обновляется только если prop изменился по значению
Object.is); - большие реактивные объекты, из которых компонент читает слишком много;
- computed, возвращающий новый объект при каждом пересчёте;
- частые
watchсо сложной логикой.
<!-- каждый рендер создаётся новый объект -> ребёнок обновляется -->
<Child :style="{ color: theme }" />
<!-- стабильная ссылка -->
<Child :style="childStyle" /> <!-- const childStyle = computed(() => ({ color: theme.value })) -->Как искать
Vue DevTools: подсветка обновлений компонентов и Timeline; onRenderTriggered показывает причину рендера.
onRenderTriggered(e => console.log('triggered by', e.key, e.target))Правило
Сначала измерить, потом оптимизировать. Мемоизация имеет цену (память, сложность), и на маленьких компонентах не окупается.
Вопросы с ответами
Чем Vue отличается от React в вопросе ре-рендеров?
Vue отслеживает зависимости автоматически и обновляет точечно; в React по умолчанию перерисовывается всё поддерево, поэтому нужны
memo,useMemo,useCallback.
Как узнать, почему компонент перерисовался?
Хук
onRenderTriggeredили Vue DevTools.