Представляем v-memo — новую директиву для повышения производительности приложений Vue 3

Vue 3 предоставил нам несколько значительных улучшений производительности из коробки, но также ввел некоторые дополнительные функции, которые могут помочь улучшить производительность наших приложений.

В этой статье мы рассмотрим новую директиву под названием v-memo. Эта директива появилась в Vue 3.2 и, насколько мне известно, не будет доступна в Vue 2. Цель этой директивы — помочь вам улучшить производительность вашего среднего/большого приложения Vue, и она не предназначена для использования в небольших приложениях.

Что делает v-memo?

Определение v-memo следующее:

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

Что такое v-memo

Даже если приведенное выше предложение может показаться пугающим, на самом деле все довольно просто для понимания. Директива v-memo делает то же самое, что уже происходит с нашими вычисляемыми свойствами, но только применяется к части DOM.

Эта новая директива будет кэшировать часть DOM, которую она контролирует, и просто запускать обновление и повторное отображение, если определенное значение изменится. Эти значения устанавливаются разработчиками вручную.

Базовый пример v-memo.

Примеры — это всегда лучший способ понять новые технологии, поэтому давайте сразу перейдем к небольшому примеру, чтобы начать и увидеть синтаксис и использование этой директивы:

<template>
  <div>
    ..the rest of the component
    <div v-memo="[myValue]">
      <svg >
        <title>{{MyValue}}</title>
        ...
      </svg>
      <vue-custom-element :value="myValue"></vue-custom-element>
    </div>
  </div>
</template>
Войти в полноэкранный режим Выйти из полноэкранного режима

Давайте посмотрим подробнее, что достигается вышеуказанным способом:

...the rest of the component
Войти в полноэкранный режим Выйти из полноэкранного режима

Первое, что требует объяснения, это то, что v-memo обычно используется как часть компонента, и он должен влиять только на подмножество доменов компонента. Поэтому в данном примере мы ожидаем, что компонент будет больше, чем то, что я только что вставил выше.

<div v-memo="[myValue]">
Вход в полноэкранный режим Выход из полноэкранного режима

Далее, мы назначили наш v-memo определенному DIV и всем его дочерним элементам. При вызове v-memo мы должны передать массив значений, которые будут управлять рендерингом поддерева.

Массив принимает одно или несколько значений v-memo="[valueOne, valueTwo]«, а также выражения типа v-memo="myValue === true".

Примечание: Вызов v-memo с пустым массивом будет эквивалентен использованию v-once и отрисует эту часть компонента только один раз.

<svg >
  <title>{{MyValue}}</title>
  ...
</svg>
<vue-custom-element :value="myValue"></vue-custom-element>
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь пришло время сосредоточиться на содержимом нашего поддерева. В моем примере я использовал родной элемент «SVG» и пользовательский элемент Vue «vue-custom-element». Я сделал это, чтобы подчеркнуть тот факт, что HTML, включенный в v-memo, может быть абсолютно любым.

Когда наш внутренний HTML является собственным элементом (div, SVG, кнопка, форма), использование v-memo будет полезно только при использовании очень больших наборов данных (например, больших таблиц) или очень сложных вложенных DOM, как в случае с динамическим SVG.

В то время как использование v-memo в пользовательском компоненте не только остановит рендеринг HTML, но и фактически остановит реактивное обновление компонентов Vue (watch, computed и т.д.). При использовании с пользовательским элементом Vue, v-memo может быть очень полезен в ситуациях, когда рендеринг дочернего компонента очень затратен, и мы можем «отложить» его обновление до определенных сценариев.

Несколько примеров

В этом разделе будет приведена пара быстрых примеров, чтобы обеспечить больший контекст и помочь понять, когда эта функция будет действительно полезна.

Я хотел бы подчеркнуть, что эта функция предназначена для опытных пользователей и должна использоваться только в сложных приложениях, где небольшие улучшения производительности действительно важны.

Неправильный случай

Я начну с того, что напишу, когда использование v-memo на самом деле неправильно и не даст никаких преимуществ в производительности.

<div v-memo="[myValue]">
  <p>Static content, no vue values here</p>
</div>
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше примере поддерево, включенное в v-memo, не нужно запоминать, так как оно фактически статично и не будет меняться (оно не включает ни одной переменной Vue). Управление виртуальным DOM в Vue 3 способно автоматически понять, какая часть DOM статична, а какая нет.

Добавление v-memo в статический HTML не будет полезным, независимо от того, насколько сложным является HTML.

Управление обновлениями

Есть случаи, в которых v-memo можно использовать не только для повышения производительности, но и для улучшения пользовательского опыта (UX), управляя циклом обновления компонента.

<div v-memo="[allFieldChanged]">
  <p>{{ field1 }}</p>
  <p>{{ field2 }}</p>
  <p>{{ field3 }}</p>
  <p>{{ field4 }}</p>
</div>
Вход в полноэкранный режим Выход из полноэкранного режима

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

Недавно у меня была ситуация, когда дочерний компонент обновлял и реагировал на большой набор данных JSON. В этом случае использование v-memo действительно помогло просто запустить обновление, когда все изменения были завершены.

Используйте его в сочетании с v-for

Один из наиболее распространенных случаев использования v-memo — это работа с очень большими списками, отображаемыми с помощью v-for.

<div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
  <p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>
  <p>...more child nodes</p>
</div>
Вход в полноэкранный режим Выход из полноэкранного режима

В приведенном выше примере, взятом непосредственно из документации Vue, мы видим синтаксис v-for / v-memo на практике.

Без использования v-memo в приведенном выше коде, каждое изменение переменной «selected» приводило бы к полному повторному отображению списка. Запоминание, обеспечиваемое новой директивой, позволяет фреймворку просто обновлять строки, в которых изменяется выражение item.id === selected, следовательно, когда элемент выбран или не выбран.

Если мы рассмотрим список с 1000 элементами. Использование v-memo с приведенным выше кодом позволит сэкономить на оценке и повторном отображении 998 записей для каждого изменения! Неплохо!

Непроизвольная остановка дочернего компонента для запуска обновлений

Последний пример — это крайний случай, с которым я недавно столкнулся. В большей части этой статьи мы подчеркивали тот факт, что v-memo остановит поддерево от рендеринга обновления, но важно понимать, что использование этой директивы фактически остановит выполнение любого кода, который может быть вызван обновлением.

Рассмотрим следующий пример:

<div v-memo="[points > 1000]">
  <myComponent :points="points" />
</div>

//myComponent
<isLevel1 v-if="points <= 1000">....</isLevel1>
<isLevel2 v-if="points > 1000">...</isLevel2>
<script>
...,
watch: {
  points() {
    logPointChange();
  }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Если предположить, что внутренние компоненты «isLevel1» и «isLevel2» являются сложными, то избежать их рендеринга с помощью v-memo кажется хорошей идеей. К сожалению, избегая повторного рендеринга, вы также избежите выполнения любого кода внутри myComponent. В нашем примере это означает, что часы, зарегистрированные на свойстве «points», не будут запущены, пока переменная «points» не изменится между пороговыми значениями уровня.

Эту проблему довольно легко решить, поскольку все, что нам нужно сделать, это переместить метод log в родительский компонент, но важно помнить, что выполнение полностью усекается использованием v-memo.

Резюме

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

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

Оцените статью
devanswers.ru
Добавить комментарий