Здравствуйте. Перевод данной статьи подготовлен специально для студентов курса «Разработчик JavaScript», который стартует уже на следующей неделе.


Голос Чуи

Немного обо мне — меня зовут Вайбхав, я из Five2One. Я вовлечен во VueJS уже целых 2 года (с момента выхода 1.0) и в основном помогал создавать/обучать 3 из крупнейших кодовых баз VueJS в Сиднее. Этот код служит миллионам людей, поэтому моя задача — не просто создавать масштабируемые паттерны кода, а еще и в значительной степени заботиться о его производительности.

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

Давайте перейдем прямо к делу — поговорим о некоторых простых способах повышения производительности вашего приложения VueJS.

Номер один



Что мы здесь видим так это «functional» шаблон, который не имеет объявленного состояния и имеет дело только с props. Его можно легко создать в functional компоненте на основе Vue с помощью рендеринг-метода.

https://vuejs.org/v2/guide/render-function.html

Если вы прочитаете это, вы увидите передачу props с functional: true
Итак, простое исправления для этого решения ниже:



Вот так просто, вам не нужно беспокоиться об изменении синтаксиса шаблона, вы можете придерживаться его и при этом наслаждаться роскошью синтаксиса Vue.
БЫСТРАЯ ПРАВКА: Поскольку это functional компонент, его контекст не существует, поэтому для доступа к props необходимо применить props.name — спасибо Динешу Мадханлалу за упоминание

Второй простой способ


Использование keep-alive для динамически загружаемых компонентов.



Иногда мы загружаем компоненты «на лету» с помощью Vue. Мы можем переключаться между компонентами, которые загружаются динамически. Для того чтобы мы могли поддерживать состояние и предотвращать повторную загрузку данных при переключении компонентов, оболочка DOMless является хорошим решением для ускорения процесса



Третий простой способ


Этот будет немного более очевиден для большинства, если учитывать, как работает система vDOM во Vue. Цель vDOM — действовать в качестве промежуточного средства обновления и отслеживать (очень эффективно) изолированные изменения в пользовательском интерфейсе проекта и запускать изолированные повторные визуализации для этих целевых компонентов вместо перерисовки всего экрана.



Зачастую мы можем создать компонент, который имеет оболочку, которая многократно рендерится, и какая-то другая часть того же шаблона должна выполнять МНОГО работы, всякий раз, когда другая часть шаблона перерисовывается. Простое решение — просто разбить файл на компоненты. Если ребенок не зависит от родителя по отношению к данным, он должен обрабатываться без проблем.



Четвертый простой способ


Использование анонимных функций в событиях CTA. Всякий раз, когда анонимная функция передается в «onClick» кнопки (я видел этот шаблон среди разработчиков, которые приходят из React, потому что это один из способов в React передавать пользовательские данные в функцию), лучше не передавать анонимную функцию. Причина такова.

Рассмотрим пример ниже:



Что здесь происходит так это то, что каждый раз, когда div увеличивается в длине (например прогрессбар), все кнопки также будут перерисовываться.

Технически они не должны, потому что ничего в них не меняется, верно? Нет обновления props или обновления данных и т.д.

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

К счастью, Vue настолько удивителен, что он достаточно умен, чтобы понимать, что никакая функция, вызываемая самостоятельно, не должна вызываться до тех пор, пока не сработает событие, к которому она присоединена, поэтому даже если это IIF, Vue делает ее thunk, что задерживает выполнение.



Если вы хотите обезопаситься, всегда стоит создавать замыкание, которое возвращает другую функцию, поэтому функция-обертка имеет только один экземпляр и не вызывает повторного рендеринга.

Волшебный 5-й простой способ


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

Да, я говорю об использовании v-if или v-show. Существует огромная разница между ними. V-if = false никогда не рендерит компонент с отключенной директивой. Поэтому, если этот компонент переключается несколько раз за короткий промежуток времени, это повлияет на производительность, поэтому использование v-show в таких ситуациях работает очень хорошо.

Однако подвох заключается в том, что в ситуации, когда вы добавляете v-show к компоненту, и этот компонент должен выполнить тяжелую операцию при первом его рендеринге, тогда эта операция будет выполняться независимо от того, является ли v-show истиной или ложью. Стоит отложить его, используя v-if, пока этот компонент действительно не понадобится. Помните, что v-show устанавливает только отображаемое значение CSS для отображаемого компонента: никакого, если компонент все еще «рендерится».

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

Я надеюсь, что это помогло вам всем!

Если вам понравилось это, обязательно подписывайтесь за подобными темами:
twitter: twitter.com/@veebuv

Вот такой получился перевод. Ждем ваши комментарии, друзья.

Комментарии (7)


  1. Spunreal
    19.06.2019 16:41

    3 и 4 способы ещё можно понять, но вот 1, 2 и 5 — это ж просто документация.

    БЫСТРАЯ ПРАВКА: Поскольку это functional компонент, его контекст не существует, поэтому для доступа к props необходимо применить props.name — спасибо Динешу Мадханлалу за упоминание

    Примечание: в версиях до 2.3.0 опция props необходима, если вы хотите использовать входные параметры в функциональном компоненте. С версии 2.3.0 и выше вы можете опустить опцию props и все атрибуты, найденные на узле компонента, будут неявно извлечены в качестве входных данных.


  1. AndreasCag
    19.06.2019 19:53
    +3

    Выбрали плохую статью и сделали плохой перевод :(

    Это предложение вообще за гранью:

    К счастью, Vue настолько удивителен, что он достаточно умен, чтобы понимать, что никакая функция, вызываемая самостоятельно, не должна вызываться до тех пор, пока не сработает событие, к которому она присоединена, поэтому даже если это IIF, Vue делает ее thunk, что задерживает выполнение.


    Четвертый способ полная глупость.
    Что здесь происходит так это то, что каждый раз, когда div увеличивается в длине (например прогрессбар), все кнопки также будут перерисовываться.

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

      <button @click="() => $logger.log('lol')">Test</button>
      <button @click="$logger.log('lol')">Test</button>
    

    Автор утверждает (хотя тяжело понять в тексте что он там на самом деле утверждает), что во втором случае не будет создаваться новая функция при ререндере, но это не так, так как все в итоге будет скомпилировано vue-template-compiler'ом в это:

    _c(
      "button",
      {
        key: i,
        on: {
          click: function() {
            return _vm.$logger.log("lol")
          }
        }
      },
      [_vm._v("Test")]
    )
    

    Т.е. новая функция будет все-равно создаваться при ререндере. Оптимизации внутри шаблонов обещают только во Vue 3 версии.


  1. CyberAP
    19.06.2019 20:06

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


    Например, вы полностью лишаетесь автоматического пробрасывания атрибутов в рутовый элемент и эту логику вам придётся реализовывать самому. Простого v-bind="$attrs" здесь не хватит, потому что у Vue есть два типа классов в data: class и staticClass, оба из которых нужно прокидывать. Так же вы лишены возможности использовать другие компоненты внутри функционального компонента как раньше, для этого вам придётся использовать пропы или inject с дефолтными значениями.


    Для таких компонентов как в первом примере, который просто отображает данные из пропов я бы посоветовал использовать v-once, если вы на все 100% уверены что этот компонент не будет изменяться.


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


  1. Quilin
    19.06.2019 21:26

    Два года в vuejs. Начинал с первой версии. Я три с половиной года назад писал spa на второй версии. Или у товарища так себе с актуализацией технологии, или статья морально устарела.


  1. zoroda
    20.06.2019 15:25

    Такой сложный язык! У меня мозг вкипел от перлов:

    Этот будет немного более очевиден для большинства

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

    Этот такой же простой, относительно него есть серые зоны, и это не общее решение.

    Я надеюсь, что это помогло вам всем!

    «Это» помогло.
    Переводчик, тебе не жалко людей, которые это читают?
    Переведи это на русский либо оставь на английском. Гугл транслейт, полагаю, тут все умеют.
    Сочувствую всем, кто проходит ваши «Авторские онлайн?курсы для профессионалов»


    1. MaxRokatansky Автор
      20.06.2019 17:01

      Добрый день. Благодарим за комментарий, учтем на будущее и обязательно проведем беседу с переводчиком на тему «сложности языка». Что касается курсов, мне кажется, довольно странно делать выводы о курсах по статье в блоге…


  1. NerVik
    20.06.2019 19:36

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