Мемоизация и лишние ре-рендеры

↑ 7.2 Рендеринг и производительность · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: senior

Зачем это на собесе

Вопрос на понимание, что вызывает рендер и как остановить лишнюю работу без преждевременной оптимизации.

Что вызывает рендер компонента во 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))

Правило

Сначала измерить, потом оптимизировать. Мемоизация имеет цену (память, сложность), и на маленьких компонентах не окупается.

Вопросы с ответами