strokoff

Оптимизируем Vue.js приложение при помощи ‘v-once’ и ‘v-memo’

v-once v-memo vuejs

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

Vue.js как и любой другой инструмент, который мы используем в интернете — очень сильно зависит от того, как вы его используете. Если вы напишете плохо оптимизированный код, вы получите медленный веб-сайт, даже если он написан на последней версии Vue.js  Поэтому сегодня мы рассмотрим, как можно оптимизировать производительность с помощью двух малоизвестных HTML-атрибутов Vue, известных как v-once и v-memo. Оба они позволяют нам оптимизировать процесс повторного рендеринга компонента или дерева компонентов.

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

v-once

В данном примере у нас есть реактивная переменная message, которая по умолчанию у нас равна «hello world» по клику на кнопку мы изменяем сообщение на «Goodbye world», значение message мы используем как контент для h1 тега так и в качестве value у поля ввода

Хотя при нажатии на кнопку значение ввода будет обновлено, h1 по-прежнему будет иметь старый текст Hello World, поскольку он имеет атрибут v-once. По сути, h1 обрабатывается только один раз и больше никогда не обновляется. Это очень полезно для использования переменных и их обновления в одних местах, но не в других. Это также очень полезно для оптимизации вашего кода! Это также относится к любой переменной, упомянутой в <h1> или ее дочерних элементах — вся структура отображается только один раз.

v-once можно использовать практически везде, в том числе в циклах v-for, что делает его универсальным в Vue.js.

v-memo 3.2+

v-memo директива для поддерева шаблона. Может использоваться как на элементах, так и на компонентах. Директива ожидает, что массив значений зависимостей фиксированной длины будет сравниваться с запомненным. Если каждое значение в массиве было таким же, как при последнем рендеринге, обновления для всего поддерева будут пропущены. Например:

<div v-memo="[valueA, valueB]">
...
</div>

При повторном рендеринге компонента, если и значение A, и значение B остаются прежними, все обновления для этого <div> и его дочерних элементов будут пропущены. На самом деле, даже создание VNode Virtual DOM также будет пропущено, поскольку запомненную копию поддерева можно использовать повторно.

Важно правильно указать массив для запоминания, иначе мы можем пропустить обновления, которые действительно должны быть применены. v-memo с пустым массивом зависимостей (v-memo=»[]») будет функционально эквивалентен v-once.

Использование с v-for

v-memo предоставляется исключительно для микрооптимизации в критических для производительности сценариях и в действительности очень редко требуется. Наиболее распространенный случай, когда это может оказаться полезным, — это рендеринг больших списков v-for (где длина > 1000) и каждый элемент списка может быть отдельным сложным компонентом.

<div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
  <p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>
  <p>...другие вложенные элементы и компоненты</p>
</div>

Когда выбранное состояние компонента изменится, будет создано большое количество виртуальных узлов, даже если большинство элементов остались точно такими же. Использование v-memo здесь, по сути, говорит: «обновлять этот элемент только в том случае, если он перешел от невыбранного к выбранному или наоборот». Это позволяет каждому незатронутому элементу повторно использовать свой предыдущий виртуальный узел и полностью пропустить изменение и рендеринг. Обратите внимание, что нам не нужно включать item.id в массив зависимостей memo здесь, поскольку Vue автоматически выводит его из аттрибута :key элемента.

ВАЖНО

При использовании v-memo с v-for убедитесь, что они используются для одного и того же элемента. v-memo не работает внутри v-for.

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

Прелесть v-memo в том, что если у нас есть ситуация, когда несколько переменных всегда будут обновляться одновременно, мы можем избежать многократного повторного рендеринга. Давайте посмотрим на модифицированную версию кода, который мы использовали для v-once. Здесь у нас теперь две переменные — message и question. Каждое обновление по нажатию отдельных кнопок — одна для вопроса, а другая для сообщения. Я использую v-memo для тега <h1> только для его обновления.

Если мы нажмем кнопку «Обновить сообщение», для пользователя ничего не изменится, поскольку v-memo отслеживает только изменения в сообщении, а не в вопросе, но переменная вопроса все равно будет обновляться в фоновом режиме. Однако, если мы нажмем кнопку «Обновить вопрос», то <h1> немедленно обновится, поскольку мы сказали v-memo обновлять только в случае изменения этой переменной.

Это довольно изящный трюк для оптимизации, но у него есть и другие применения. Например, вы можете обновлять элемент и все элементы/переменные внутри него только тогда, когда в вашем коде выполняется определенное условие. Единственное, что следует отметить, это то, что вы не можете использовать v-memo в цикле v-for, так что на это следует обратить внимание. Вы можете определить несколько переменных для v-memo, объеденив их в массиве, например:
<h1 v-memo="[ message, question ]"></h1>

 

Также интересно отметить, что передача пустого массива заставляет v-memo работать так же, как v-once 😄

<h1 v-memo="[]"></h1>

 

Надеюсь эти несколько простых примеров, помогут вам избегать лишних вычислений и ререндеров вашего vue,js приложения в будущем. Буду рад дополнить статью на основе ваших комментариев.

Ссылки по теме:


Последняя редакция 16 января, 2023 в 11:01