Вышел Vue.js 3.0 «One piece»

Original author: Evan You
  • Translation

Название - это отсылка к манге "One piece" про парня, который хочет стать пиратским королем, прим. перев.

Сегодня мы с гордостью объявляем об официальном выпуске Vue 3.0 «One Piece». Эта новая мажорная версия фреймворка с повышенной производительностью, меньшим размером, лучшей поддержкой TypeScript, новыми API-интерфейсами для крупномасштабных проектов (а для средних - можно избавиться от vuex, прим. перев.) и прочной основой для будущих итераций платформы.

Версия 3.0 - это более двух лет усилий по разработке, включающих 30+ RFC, 2600+ коммитов, 628 пулл-реквестов от 99 участников, а также огромный объем работы по разработке и написанию документации за пределами основного репозитория. Мы хотим выразить нашу глубочайшую благодарность членам команды за то, что они взяли на себя эту работу, нашим контрибуторам за пулл-реквесты, нашим спонсорам за финансовую поддержку, а также сообществу за участие в обсуждениях дизайна и отзывам на предрелизные версии. Vue - это независимый проект, созданный для сообщества и поддерживаемый сообществом, и Vue 3.0 был бы невозможен без вашей постоянной поддержки.

Развитие концепции "Прогрессивного фреймворка"

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

Сегодня Vue используют более 1,3 миллиона пользователей (это число основано на количестве активных пользователей за неделю у расширения Chrome Vue Devtools в соответствии со статистикой Google) (я так и не понял, включает ли это число пользователей расширения для firefox, прим. перев.) и мы видим, что Vue используется в самых разнообразных сценариях, от добавления интерактивности на "традиционные" страницы, генерируемые на сервере, до полноценных одностраничных приложений с сотнями компонентов. Vue 3 расширяет эту гибкость.

Многослойные внутренние модули

Vue 3.0 по прежнему можно использовать из CDN с помощью тега <script>, однако его внутреннее устройство было переписано с нуля в набор раздельных модулей. Новая архитектура обеспечивает лучшую управляемость и позволяет сократить время выполнения в некоторых случаев в два раза, за счет tree-shaking.

Эти модули также предоставляют более низкоуровневое API, благодаря которому можно делать самые разные продвинутые вещи:

  • Компилятор поддерживает трансформацию абстрактного синтаксического дерева (AST) в процессе сборки, например для интернационализации

  • Ядро предоставляет первоклассное API для создания своих визуализаторов, для рендеринга не только в браузере, но и, например, на мобильных устройствах, в контексте WebGL или в консоли. Базовый DOM-визуализатор использует этот же API

  • Модуль @vue/reactivity экспортирует функции, которые обеспечивают прямой доступ к системе реактивности Vue, и может использоваться как отдельный пакет. Его можно использовать в паре с другими решениями для создания шаблонов (например, lit-html) или даже в сценариях без пользовательского интерфейса.

Новые API для крупных приложений

Объектный API версии 2.x практически полностью поддерживается в Vue 3. Однако в версии 3.0 также представлен Composition API - новый набор API, направленных на устранение проблем при использовании Vue в крупномасштабных приложениях. Composition API построен на основе ранее упоминавшегося API реактивности. Он обеспечивает логическую связность и возможность повторного использования, похожую на хуки React, что позволяет более гибко организовывать код и надежнее определять типы (по сравнению с объектным API 2.x).

Composition API также можно использовать в Vue 2.x через плагин @vue/composition-api, и уже существуют библиотеки на базе Composition API, которые работают как для Vue 2, так и для 3 (например, vueuse, vue-composable).

Улучшение производительности

Vue 3 показывает значительные улучшения производительности по сравнению с Vue 2: размер пакета (до 41% меньше при использовании tree-shaking), первичный рендеринг (до 55% быстрее) и обновление отображения (до 133% быстрее), использования памяти (до 54% меньше).

В Vue 3 мы использовали подход «виртуальный DOM с информацией от компилятора» (compiler-informed Virtual DOM, как лучше перевести - не знаю, прим. перев.): компилятор шаблона выполняет агрессивную оптимизацию и генерирует код рендер-функции, который отделяет статический контент, оставляет подсказки для определения типов и, что наиболее важно, выравнивает (flatten, прим. перев.) динамические узлы внутри шаблона для снижения стоимости обхода дерева документа во время выполнения. Таким образом пользователь получает лучшее из обоих миров: оптимизированную компилятором производительность при использовании шаблонов или непосредственное управление рендерингом с помощью рендер-функции, если нужно.

Улучшенная интеграция с TypeScript

Кодовая база Vue 3 написана на TypeScript с автоматически сгенерированными, протестированными и объединенными определениями типов, поэтому эти определения всегда актуальны. Composition API отлично работает с выводом типов. Vetur, наше официальное расширение VSCode, теперь поддерживает проверку типов у шаблона и свойств (props прим. перев.) с использованием улучшенной внутренней типизации Vue 3. Кстати, определение типов полностью поддерживаются в TSX, если он вам больше нравится.

Экспериментальные возможности

Предлагаем вам две новые функции для однофайловых компонентов (SFC, также известные как файлы .vue):

Эти функции уже реализованы и доступны в Vue 3.0, однако предоставляются только для сбора отзывов. Они останутся экспериментальными до тех пор, пока соответствующие RFC не будут приняты.

Мы также реализовали недокументированный компонент <Suspense>, который реализует ожидание вложенных асинхронных зависимостей (асинхронные компоненты или компоненты с async setup()) при начальном рендеринге или перерендеринге при изменении ветвей (v-if и т.п.). Мы тестируем эту функциональность вместе с командой Nuxt.js (Nuxt 3 уже готовится) и, вероятно, утвердим её к версии 3.1.

Постепенный выпуск

Выпуск версии 3.0 обозначает общую готовность фреймворка. Несмотря на то, что некоторым из подпроектов фреймворка может потребоваться доработка для достижения стабильного статуса (в частности, интеграция vue router и Vuex в инструменты разработки), мы считаем целесообразным начинать новые проекты с нуля с Vue 3 уже сейчас. Мы также рекомендуем авторам библиотек начать обновлять ваши проекты для поддержки Vue 3.

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

Миграция и поддержка IE11

Мы отозвали сборку для миграции (сборка v3 с поведением, совместимым с v2 + предупреждения о несовместимых возможностях для упрощения миграции) и сборку с поддержкой IE11 из-за ограничений по времени. Мы сосредоточимся на их выпуске в 4 квартале 2020 года. Если вы планируете миграцию существующего приложения v2 или вашему приложению требуется поддержка IE11, вы должны знать об этих ограничениях.

Дальнейшие шаги

В ближайшее время мы сосредоточимся на:

  • Сборка для миграции

  • Поддержка IE11

  • Интеграция Router и Vuex в новые инструменты разработчика

  • Дальнейшие улучшения вывода типов в шаблонах в Vetur

В настоящее время веб-сайты с документацией, ветки на GitHub и теги npm для проектов Vue 3 и подпроектов, ориентированных на третью версию Vue, будут оставаться со статусом next. Это означает, что npm install vue по-прежнему будет устанавливать Vue 2.x, а npm install vue@next установит Vue 3. К концу 2020 года мы планируем переключить все ссылки на документацию, ветки и теги по умолчанию на 3.0.

В то же время мы планируем выпуск версии 2.7, который будет последним минорным выпуском линейки 2.x. В 2.7 будет выполнен обратный перенос совместимых улучшений из версии 3 и выдача предупреждений об использовании API, которые были удалены/изменены в версии 3, чтобы помочь с потенциальной миграцией. Мы планируем работать над версией 2.7 в первом квартале 2021 года. Этот выпуск станет LTS-версией с периодом поддержки 18 месяцев.

Попробовать

Вы можете больше узнать о Vue 3.0 на новом веб-сайте. Если вы уже являетесь пользователем Vue 2.x, перейдите непосредственно к разделу, посвященному миграции.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 94

    0
    у меня в последнем cli написано preview
      0
      Речь про vue или про vue-cli? Сам vue релизнулся, всякие vue-cli и прочие вещи с v3.vuejs.org/guide/migration/introduction.html#supporting-libraries по большей части отмечены как пререлизы. Об этом в статье написано.
      UPD: проверил. При создании из vue-cli действительно так.
      +1
      Я не могу найти ссылку на оригинальную статью. Ссылка в заголовке ведет на гитхаб
      0
      Знаменательный момент для всех кто на Vue!
      Придется переезжать на 3 версию. Страшно, но заманчиво.
        +1

        Ага особенно весело разработчикам всяких плагинов и ui библиотек. Наша песня хороша, начинай сначала

          0
          Ну все таки это не так больно, как с python. А новые апи действительно дают много хороших возможностей (хотя может быть даже слишком много :))
            0
            Было бы здорово, если бы кто-то сделал скрипт, который конвертирует vue2->vue3 :)
            Ну либо доходчиво расписал, что менять надо.
      0
      Поддержка тайпскрипта условная к сожалению, потому что в шаблонах тайпчекинга нет, чисто в IDE подсказки есть с автокомплитом, но если поменялся интерфейс и в шаблонах использованы не актуальные имена полей, то вам об этом никто не скажет. Все молча соберется без ошибок.
        0
        Пробовали vetur.validation.props установить в true?
          –1
          Причем тут настройка плагина для IDE и сборка проекта, которая не падает при нарушении типизации?
            0
            Понял, о чем речь. В качестве обходного решения можно добавить vti в конвейер сборки, он будет ругаться на неправильные/отсутствующие props.
              0
              WIP. This feature is not stable yet.
              Плюс это костыль и хотелось бы это из коробки, раз речь идет о поддержке Typescript'a.
                0
                Ну да, костыль. просто я его себе с пол года назад настроил и забыл :)
                  –1
                  как именно в режиме разработки?
                    0
                    В прекоммит. Ну а при работе в IDE он и так показывает косяки.
                      –1
                      Так во время сборщика при разработки их тоже видить надо где поломались файлы, а не только во время коммита или когда файлы открыт в IDE
                        0
                        Ну добавьте в скрипт сборки эту команду в конвейер непосредственно перед командой сборки. Например
                        vti diagnostics && vue-cli-service build

                        Единственное, что будет не совсем правильно работать — hot reload. Но терпимо.
                          0
                          Ну в целом сойдет, но конечно если бы тайпчекинг работал из коробки было бы круто
        +4
        Зачем они поддержку IE11 тащат? Кому IE нужен может на второй ветке остаться. Так где нужна поддержка IE11 вряд ли озабочены актуальностью версий фреймворков.
          0
          Ну вот, например, мне нужна поддержка IE11. И, как минимум, достаточно немалое увеличение производительности 3-й версии тоже хотелось бы. Да и под вопросом стоит, а будет ли кто-то еще разрабатывать под вторую версию (ui-либы там и т.д.)
            0
            Я не знаю где вам IE11 понадобился, сейчас куча людей на FireFox уже забивает, хотя его поддержку обеспечить не так сложно.

            Сколько пользователей у вас на IE11 в %?
              0
              -5% в среднем
          0
          Пока vuetify не перешли, тоже не будут. Рано пока.
            0
            Мы планируем работать над версией 2.7 в первом квартале 2021 года. Этот выпуск станет LTS-версией с периодом поддержки 18 месяцев.

            А потом «почему все смеются над JS-экосистемой». Да потому что в прошлом году начали крупный проект на актуальном, модном, и современном VueJS, а уже через полтора года окажется что у нас фронт построен на устаревшем фреймворке у которого вот-вот закончится поддержка. Меньше трёх лет, с состояния «на самых новых технологиях» в состояние «жуткое легаси». И как вот с этим жить вообще? Надеюсь сообщество форкнет последнюю версию 2.х, и будет развивать её параллельно.
              +1
              А потом «почему все смеются над JS-экосистемой». Да потому что в прошлом году начали крупный проект на актуальном, модном, и современном VueJS, а уже через полтора года окажется что у нас фронт построен на устаревшем фреймворке у которого вот-вот закончится поддержка. Меньше трёх лет, с состояния «на самых новых технологиях» в состояние «жуткое легаси». И как вот с этим жить вообще? Надеюсь сообщество форкнет последнюю версию 2.х, и будет развивать её параллельно.

              Просто JS развивается очень быстро и стремительно, и дело не в Vue.js, Angular, React и т.п. Просто сам по себе код который ты писал 2 года назад, он хочешь того или нет превращается в легаси. Как минимум по тому, что ты сам становишься умнее и растешь.
              Меняешь работу, уходишь на новый проект с чистого листа и ты всегда на гребне волны. Ибо чахнуть в легаси коде такое себе удовольствие и перспектива, хотя для кого то это норма и в порядке вещей, но тут уже сколько людей столько и мнений.
                0
                Из часто используемого там — неглобальный инстанс vue, вынесенные за скобки инстанса $nextTick и подобные, самое сложное — дефолтные значения props не имеют доступа к this и v-model поменялся (зато теперь несколько переменных можно связывать независимо с меньшим количеством букв и появился доступ к модификаторам, например v-model.number). Ну и фильтры выпилены. В общем, почитав соответствующий раздел сделал вывод, что если тесты есть, то можно перейти за несколько дней на новую версию даже на крупных проектах. Я на паре своих внутренних проектов попробовал в отдельной ветке — заняло пару часов.
                  0
                  Если у вас в проекте больше своей логики, и нет острой зависимости от сторонних плагинов, ничего страшного нет, если вы перейдете на новую версию когда будет удобно Вам. JS очень гибкий, и зачастую нет нужды кидаться и переписывать все полностью. У нас стратегия мягкого перехода, мигрируем постепенно модуль за модулем, когда на это есть ресурсы.
                  0

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

                    +1
                    На Vue 2 можно уже давно писать такие же приложения как и на React и Angular. А по удобству и скорости разработки — он уже давно опередил их. С выходом Vue 3 он просто уходит в отрыв.

                    А мантра про новичков — я понимаю откуда возникает. Истратить годы на понимание старого фреймворка, и глядеть на то, как люди обучаются новому за недели — это больно. Вот и приходиться тешить ЧСВ — я мол на фреймворке не для новичков работаю. А вот примера, что можно на React или Angular и нельзя на Vue, почему-то не приводят.
                      +2
                      А вот примера, что можно на React или Angular и нельзя на Vue, почему-то не приводят.

                      • Фрагменты до Vue3, ЕМНИП, нельзя было использовать.
                      • Ну и observable модель лежащая в основе Vue на любителя. Они зачем-то реализовали зависимость одного computed значения от другого путём полной переподписки на все зависимости второго (О_о). Наверное так проще, но как блин с этим жить, в случае когда модель данных большая и тесно переплетённая? Возможно во Vue3 это поправили, не знаю. Не следил
                      • Поддержка TS в шаблонах, судя даже по этой статье, пока в зачаточном состоянии.
                      • Если не исповедовать принцип 3в1 (стили + код + шаблон в одном файле), то возникали бубны с прекомпиляцией шаблонов. Там были сложности. Я создавал issue, и получил от команды разработчиков ответ, что всё что не 3в1 это не канон, так что шёл бы я лесом. Ну такое. А писать множество крошечных компонент в рамках одного файла в 3в1, кажется, нельзя. Для меня это уже сильный аргумент против. Сильно мешает декомпозиции, которую я очень люблю. В React такой проблемы нет от слова совсем.

                      Знай я Vue побольше, мог бы сравнить плотнее. Из того что понравилось — очень вкусный шаблонизатор. JSX со своими &&, ?:, .map((item, idx) => ()) и рядом не стоял. Много синтаксического сахара в виде таких штук как .prevent, .keyDown.enter, .passive и пр. (за точность не ручаюсь, пишу по памяти). Нативная поддержка слотов.


                      P.S. Я не Vue-hater, но захоти я писать с observable, я бы, наверное, попробовал бы React + MobX, или React + RxJS. Vue сильно ужалил своим watcher.demand и переподпиской. И отсутствием фрагментов (были только криво работающие костыли) тоже. Однако очень приятно наблюдать, что он быстро развивается. Этакий KnockoutJS с человеческим лицом (и ужасной моделью observable)

                        0
                        Все нормально с реактивностью во vue сейчас, особенно в версии 3. Тем более никто и ничто не мешает использовать Vue в паре с MobX, я пробовал, они отлично дружат.
                          0
                          ничто не мешает использовать Vue в паре с MobX

                          Охотно верю. Но зачем?! Звучит как безумие. Особенно учитывая что во Vue3 всё торчит наружу.

                            –1
                            На случай если реактивность vue не устраивает) Меня то устраивает) Просто говорю что есть такая возможность в случае чего
                          0
                          То, что я прочел вкратце про Фрагменты — то мне кажется во Vue они и не понадобятся. В частности мне проблем с их отсутствием не встречалось.

                          Ну и observable модель лежащая в основе Vue на любителя. Они зачем-то реализовали зависимость одного computed значения от другого путём полной переподписки на все зависимости второго (О_о). Наверное так проще, но как блин с этим жить, в случае когда модель данных большая и тесно переплетённая? Возможно во Vue3 это поправили, не знаю. Не следил

                          Вообще не понятно в чем проблема. Что править-то?

                          Поддержка TS в шаблонах, судя даже по этой статье, пока в зачаточном состоянии.

                          Ну это не такая уж проблема, мне лично ни разу не помешала.

                          Если не исповедовать принцип 3в1 (стили + код + шаблон в одном файле), то возникали бубны с прекомпиляцией шаблонов. Там были сложности. Я создавал issue,

                          Ну я например принципиально пишу scss отдельно, в компоненты не включаю. Мне так удобней. С перекомпиляцией нет проблем.

                          Мне кажется, что вы переносите практики Реакта или Ангуляра на Vue, и получаются сложности. Если просто следовать рекомендациями создателей Vue и не усложнять сущностей, то все отлично и ясно устраивается. Vue + Vuex и самые стандартные практики закрывают все вопросы. Даже watchers на мой взгляд уже лишнее, я их почти не использую, они и не нужны, если все правильно спроектировать. Поэтому мне трудно понять фразу — «Vue сильно ужалил своим watcher.demand и переподпиской». Что за переподписка такая? И чем она мешает?

                          ЗЫ Лучше обсуждать не то как именно конструкцию из Реакта или Ангуляра реализовать на Вью, а саму задачу, так как подходы разные, изоморфно друг на друга не отображаются.
                            +1
                            Мне кажется, что вы переносите практики Реакта или Ангуляра на Vue, и получаются сложности

                            Честно говоря, я не горю желанием вдаваться в объяснения:


                            • почему типизация это хорошо и какие проблемы она решает
                            • почему O(n) вместо O(1) это плохо, и в каких контекстах это катастрофа
                            • почему возможность возврата не-единичной ноды сильно упрощает некоторые сложные задачи

                            Т.к. писать про это придётся очень много. С примерами. А вы, наверное, продолжите спорить в текущем ключе (аля "не нужон мне ваш инторнет этот"). Вам не нужон. А мне очень нужен. Я пишу SPA уже много лет. От очень маленьких, до очень больших. И хорошо понимаю что мне нужно от инструмента. Когда инструмент заставляет меня приседать и вставляет мне палки в колёса — это выходит боком бизнесу. Все существующие на рынке инструменты заставляют это делать. Если вы считаете, что ваш инструмент не заставляет, то вы просто приседаете, думая, что не приседаете :-) Это скорее вопрос осведомлённости и опыта. Правда такова — все существующие фреймворки очень далеки от идеала. Чтобы фанбои об этом не думали. Разработка сложных продуктов сводится к умелому лавированию между костылями и дедлайнами.

                              0
                              Типизация конечно хорошо. Но вы все-таки говорили о типизации в шаблонах. При прочих плюсах, этот недостаток не критичен.

                              «почему O(n) вместо O(1) это плохо» не надо объяснять, а вот при чем тут Vue просвятили бы уж. Никто вас не просит простыню расписывать. Можно же и кратко описать суть.

                              «возможность возврата не-единичной ноды сильно упрощает некоторые сложные задачи», выглядит голословно. Сложных задач видал много, на Vue пишу с момента выхода Vue 2, нигде не понадобилось. Интересно было узнать. И кстати для Vue 2 плагин fragments давно есть.

                                +1
                                Можно же и кратко описать суть

                                псевдокод:


                                a = computed(() => { /* touch 5000 observables */ });
                                b = computed(() => a() + 1);

                                Для вычисления b, при уже вычисленном a достаточно просто взять результат от a (который закеширован) и добавить к нему 1. KnockoutJS так бы и сделал. Помимо этого он бы автоматически подписал b на a. Таким образом при изменении значения в a, будут уведомлены все подписчики. Это пересчитает b. Vue2 (уточню — когда я его дебажил) делает не так. Он тоже берёт закешированное значение и добавляет 1. Но помимо прочего он подписывает b на все те 5000 observables, на которые был подписан a. Даже когда a уже вычислен. Т.е. просто сложить два числа — 5000 операций на подписку.


                                Затем мы берём наш b-computed и помещаем его результат в таблицу. Скажем 10 на 10. В каждую ячейку. В какой-нибудь v-bind. Все эти штуки тоже являются computed значениями. Что они делают? Ага… Копируют 5000 зависимостей. И так на каждом шаге везде по многу многу раз. Чем лучше декомпозиция, тем драматичнее эффект.


                                Как это обойти? Ну можно вместо computed на всех крупных узлах использовать watch. В моей задаче проще было выкинуть Vue, чем так уродоваться.


                                И кстати для Vue 2 плагин fragments давно есть.

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


                                Меня по первой выручил display: contents


                                выглядит голословно

                                Ок. Так и останется. Не буду ничего доказывать.


                                При прочих плюсах, этот недостаток не критичен.

                                Это шутка? Больше всего в случае React мне TS помогает как раз в props-ах. Это, имхо, самое главное.

                                  0
                                  Ну примерно ясно про что вы.

                                  ИМХО Если у вас computed зависит от больше чем трех переменных, то наверно лучше рефакторинг. Это если я вас правильно понял. Да и вообще observerables это из Реакта или Ангуляра, но мне кажется, что ко Vue это вообще не относится.

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

                                  Больше всего в случае React мне TS помогает как раз в props-ах.
                                  Говорим то о Vue. А может это индивидуально, от организации кода зависит.
                                    +1
                                    ИМХО Если у вас computed зависит от больше чем трех переменных, то наверно лучше рефакторинг.

                                    declare const students = observableArray();
                                    _.times(5000, idx => students.push(genFakeStudent(idx));
                                    const grownUpStudents = computed(() => students.filter(student => student.age >= 18));

                                    Та дам. Ваш computed зависит от 1-й переменной. Ой. Нет. От пяти тысяч. Вот жеж засада. Надо декомпозировать его на 1333 разных computed-а.


                                    Сложных задач видал много

                                    не дебажил

                                    ;-) Никогда не понимал, как можно пользоваться своим главным инструментом, не понимая, как он работает. Когда я писал с jQuery, я целыми днями утопал в их исходном коде и писал свои плагины. Когда я работал с KnockoutJS я днями утопал в дебаге всех этих хитросплетённых observables (они там в разы сложнее, чем во Vue). Когда я писал на Vue я вынужденно отлавливал причину всех этих тормозов, разбирался в принципе работы шаблонизатора и его прекомпиляции. Когда я работал (и работаю с React) я дебажу работу Fibers и их очередь. Работая с Babel и Webpack я сталкиваюсь с необходимостью написания своих плагинов для них.


                                    Какие такие сложные задачи вы решаете, которые не подразумевают дебаг и чтение сорцов? :-) Вот вы выше пишете:


                                    А вот примера, что можно на React или Angular и нельзя на Vue, почему-то не приводят.

                                    Я не уверен что вам вообще нужен ответ. Ведь "мне это не надо", "это не критично", "я бы зарефакторил", "я не сталкивался". Т.е. всё вам приводят, вам просто не интересно\не нужно.

                                      0
                                      Я не уверен что вам вообще нужен ответ. Ведь «мне это не надо», «это не критично», «я бы зарефакторил», «я не сталкивался». Т.е. всё вам приводят, вам просто не интересно\не нужно.
                                      ну зря вы так. Например водителю машины с коробкой автомат может искренне не понимать проблемы, водилы, у которого механика, и третья скорость барахлит. Я просто делюсь опытом работы с Vue.

                                      declare const students = observableArray();
                                      _.times(5000, idx => students.push(genFakeStudent(idx));
                                      const grownUpStudents = computed(() => students.filter(student => student.age >= 18));

                                      Та дам. Ваш computed зависит от 1-й переменной. Ой. Нет. От пяти тысяч. Вот жеж засада. Надо декомпозировать его на 1333 разных computed-а.


                                      Во Вью это наверное так (примерный код):
                                      const students = () => {
                                        // генерим 5000 students
                                        return students
                                      }
                                      export default {
                                        data() {
                                          return {
                                             students: students()
                                          }
                                        },
                                        computed: {
                                          grownUpStudents: () => students.filter(student => student.age >= 18))
                                        }
                                      }
                                      

                                      Судя по тому, что я знаю, Vue не будет отслеживать 5000 значений. А будет отслеживать изменения объекта в целом. Например если объекту изменили значение какого-то ключа командой Vue.set. В массиве он тоже не отслеживает поэлементно, а ждет команды типа push, и тогда считает, что было изменение.

                                      Никогда не понимал, как можно пользоваться своим главным инструментом, не понимая, как он работает.
                                      конечно понимать надо, но есть все таки понятие специализация. Доку прочитать уже неплохо )), а изучать исходники — признаюсь, не всегда.
                                        0

                                        А вы не подменяйте задачу :-)


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


                                        И если мне не изменяет память, то Vue в вашем случае как раз в глубину результат выполнения .data() и обернёт. Т.е. будет отслеживать не изменение объекта в целом, а изменение:


                                        • объекта в целом
                                        • каждого студента в отдельности
                                        • поля age у каждого студента

                                        Т.е. 5000 + 5000 + 1 зависимость. А теперь добавьте в табличку 10х10 в какой-нибудь v-bind этот computed, и смело умножайте те 10_001 на 100. В моём случае там речь шла у сотнях миллионах операций (все из которых лишние)


                                        Впрочем за это ручаться не буду, т.к. ковырял Vue последний раз года два назад. ЕМНИП то для того чтобы Vue2 не оборачивал всё в глубину своими get-ами и set-ами нужно было какой-то отдельный сторонний эпичный костыль тащить в приложение.


                                        // UPD1. на age зависимостей не будет, т.к. листья во Vue не реактивные сами по себе (как к примеру в knockout-е). Их реактивность обеспечивается get-ом объекта носителя. Так что не 5000 + 5000 + 1, а 5000 + 1


                                        // UPD2. Да я правильно запомнил, Vue в глубину проходит. Так что реактивными являются все элементы массива. Они все "115: {ob: Observer}" вот такие обёртки с отслеживанием зависимостей

                                          0
                                          Во vue вы и не сможете отдельно каждый элемент сделать реактивным, так как уже сам массив реактивен. Другой подход.

                                          А насчет
                                          На отдельно взятые элементы (и даже их поля) будут подписаны уже другие компоненты ниже по древу.
                                          , то наверное речь уже не про data родительского компонента. Такое реализуется в Vuex. Там создается также реактивный массив.
                                          Любой компонент может использовать getter из хранилицща Vuex. Например getter getAgeOfStudentNo999. И он и будет реактивен, но его изменения будут привязаны к одному объекту students из Vuex store. Так же как и все другие гетеры зависящие от students.

                                          А если все таки в одном компоненте — то делаете computed getAgeOfStudentNo999 и другие — и они все будут привязаны опять же к изменению одного объекта.

                                            0
                                            Во vue вы и не сможете отдельно каждый элемент сделать реактивным, так как уже сам массив реактивен. Другой подход.

                                            Не сможете сделать НЕ реактивным. Vue всё оборачивает за вас. Ну ей богу. Уж если вы пишете на Vue, сделайте console.log и посмотрите во что ваши массивы превращаются:



                                            то наверное речь уже не про data родительского компонента

                                            Ниже в комментарии ссылка на песочницу. Минимально переделанный ваш же код. Тот самый .data(). Святая святых Vue компонент. Удивительно что я открываю вам Эврику )


                                            Vuex использует те же observable под капотом. Они работают точно так же. Это они же (ЕМНИП). Во Vue3 они теперь доступны и простым смертным без всяких компонент.


                                            Предлагаю вам на досуге всё таки подебажить Vue. Хотя бы пробежаться по вашим моделям и поизучать их под console.log. А можно и в код заглянуть, посмотреть как устроена реактивность под капотом :)

                                          +1

                                          Поигрался в песочнице с вашим кодом. Ну собственно вроде бы ничего не поменялось.


                                          1. Да Vue сделал 5001 observable (а не 1)
                                          2. Да он сделал 5000 + 5000 + 1 + 1 подписку


                                          Vue 2.6.11


                                          А вот что происходит после добавления такого кода:


                                          computed: {
                                            test() { ... },
                                            test2() {
                                                return this.test + 1;
                                            }


                                          Заметьте уже по 3 подписки. Наш +1 как раз сюда и пролез. В каждый из observable.

                                            0
                                            может я как-то не так смотрю но показывает
                                            ​dep: {…}
                                            ​​​​​id: 208
                                            ​​​​subs: []
                                            ​​​​​​length: 0

                                            да в firefox смотрел.

                                            В Safari да, как вы говорите. Поразбираюсь.
                                              +1

                                              Ну вот я открыл ссылку и снова получил то же самое:



                                              Не знаю куда именно вы смотрите. Нужно чтобы проект запустился и test2 считался (т.е. компонент отрендерился, т.к. там всё "ленивое").


                                              В целом sandbox этот кривоват (там какие-то мутки с iframe вроде бы), так что для чистоты эксперимента можете скачать себе весь проект целиком и подебажить уже локально.

                                                +1


                                                Вот из Firefox. Впрочем было бы странно если бы это зависело от браузера

                                                  0
                                                  да это я ошибся — во всех браузерах одинаково.

                                                  да добавляются watchers, как вы и говорили. Но является ли это проблемой пока не разобрался. Почитаю, отпишусь. А что, такого поведения нету в Реакте и Ангуляре?
                                                    +1
                                                    Но является ли это проблемой пока не разобрался

                                                    Зависит от проекта. У меня был проект — приложение для построения расписания занятий для школ. Решил на нём и поиграться в боевую с Vue2. 5000 observables это всевозможные необходимые данные об учителях, учениках, кабинетах, предметах и т.д… Всё то, что нужно для формирования расписания. Там очень непростая и теснопереплетённая область.


                                                    Приложение в реальном времени должно было просчитывать возможные варианты. Например надо разметить ещё 1 урок информатики. Завуч начинает drag-n-drop у уже сразу видит какие ячейки недоступны, а какие нежелательны, а какие рекомендованы. Это вовлекает в себя пересчёт кучу данных. Целое древо калькуляций. И любое звено может быть изменено в любой момент. Т.к. можно редактировать все эти данные не отходя от кассы. И да, расписание это таблица. А таблица это X-Y ячеек. Каждая из которых это с десяток computed-ов (просто так устроен Vue). И каждая будет заниматься копированием всех этих зависимостей на любой рендер (даже холостой повторный).


                                                    Это очень просто решается при помощи observable. Но как оказалось не во Vue :) В случае Vue это выливалось в то, что он считал всё что нужно, скажем, за 3мс, а перекладывал зависимости за 900мс. Или за 5секунд. Причём дело именно в конкретной реализации, которую взяли за основу во Vue.


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


                                                    А что, такого поведения нету в Реакте и Ангуляре?

                                                    Я почти ничего не знаю про Angular. Но вот в KnockoutJS такого поведения нет. Там 5000 зависимостей будут только у А. А у Б будет всего 1. Нокаут вообще в разы сложнее устроен.


                                                    Касательно React — там нет observables. Там всё устроено совершенно иначе. Я решил ту же самую задачу на React за счёт селекторов и мемоизации. Что примечательно даже код особенно переписывать не пришлось. Просто вместо vuex.selectors & computed стали везде селекторы из reselect. Бизнес логика осталась неизменной. Чуть ли не автозаменой прошёлся.


                                                    Принцип работы всего этого под капотом совсем другой. Он не лучше и не хуже, чем observables, он другой. Так что да, такого поведения там не было.

                                                      –1
                                                      Ваша задача с расписанием может быть реализована разными способами. Эта проблема с watcher возникла из-за особенностей именно вашей реализации. Вообще я думаю логично оставить для Vue работу с интерфейсом, а логику калькуляций и т.д. поручить отдельному бизнес модулю или модулям ( данные об учителях, учениках, кабинетах, предметах — а также основную сетку и правила их взамодействий), а сводные данные нужные для построения интерфейса хранить в сторе приложения. По действиям завуча дергать методы бизнес модуля, из него же диспатчить actions в сторе. Тогда не будет проблемы 5000 observerables.

                                                      А возможно ваше решение единственно верное.

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

                                                        +1
                                                        Вообще я думаю логично оставить для Vue работу с интерфейсом, а логику калькуляций и т.д. поручить отдельному бизнес модулю или модулям

                                                        У меня так и было. Я взял Vuex. Я не писал эту логику в компонентах. Она была в отдельном слое.


                                                        Я мог бы взять какое-нибудь другое решение. Например RxJS или KnockoutJS. Или MobX. А потом изолентой скреплять этот модуль бизнес-логики с Vue (т.к. у Vue своя модель реактивности). Тогда бы оно заработало. Всё так. Один только вопрос остаётся — а на кой чёрт мне тогда Vue? Ну серьёзно. Если я беру Vue и игнорирую его реактивность, что в нём остаётся то? Шаблонизатор? Т.е. взять большой reactive framework с observable, взять стороннее observable решение для модели данных, скреплять их изолентой и выливать в продакшн? Увольте. Я просто выкинул Vue. И сейчас бы сделал точно так же. И впредь едва ли возьму Vue на серьёзные проекты, зная о таких вот приколах. Кто знает куда ещё они там воткнули O(n) шутки ради?


                                                        А вообще, я рекомендую вам воздержаться от подобных споров. Хотя бы до тех пор, пока вы свои инструменты не изучите. А то получается, что вы пытаетесь отстоять позиции Vue, которого сами не знаете. Умение писать v-bind= не эквивалентно знанию фреймворка. У нас с вами спор односторонний. Так не интересно.


                                                        Во время собеседования на Senior Frontend Developer мы обязательно спрашиваем кандидата вопросы про устройство его любимого framework-а. Будь это Vue, будь это Angular, React… Не важно. Хоть Svelte. Если человек не может внятно объяснить природу действия его главного инструмента, мы его не берём. В случае Vue мы спрашиваем как устроен паттерн observable, как работает авто-детектирование зависимостей. Если кандидат хорошо отвечает, спрашиваем какие оптимизации производительности он знает и применяет. Да, мы не делим людей на "создателей framework-ов" и "тех кто ими пользуется". Любой действительно опытный разработчик может подобный framework в упрощённом виде написать сам за неделю полторы. Если же человек пишет на ощупь, предполагая что там везде "магия"… Ну пусть пишет дальше. Но в другом месте.


                                                        Некоторые кандидаты "выпендриваются" и пишут техн. задание со своими observable "на коленке". Такое мы любим :)

                                                          –2
                                                          а логику калькуляций и т.д. поручить отдельному бизнес модулю или модулям
                                                          У меня так и было. Я взял Vuex.

                                                          не поняли вы меня совсем, я бизнес логику предложил вывести из реактивности, вне Vuex и вне Vue. Тогда ваш модуль «Расписание» можно было и к Реакту подключать, и на в ванильном JS использовать. И не пришлось бы нереактивные данные делать реактивными. Но я не senior, мне простительно.
                                                            0
                                                            Во время собеседования на Senior Frontend Developer мы обязательно спрашиваем кандидата вопросы про устройство его любимого framework-а

                                                            What the fuck?
                                                            А как устроена ваша любимая игрушка (ну шейдеры там) вы знаете?
                                                            У вас фронтенд синьёры выбирают фрейм для проекта?
                                                            Может стоит нанять project architect ?

                                                              0
                                                              Может стоит нанять project architect?

                                                              Было бы неплохо. Но к архитекту требования выше, чем к просто "синьёру".


                                                              What the fuck?

                                                              А зачем нанимать человека с амбициями "хочу много много денег", который без присмотра шагу сдвинуться не может?


                                                              На всякий случай уточню — вопросы поверхностного характера. Никто разумеется не спрашивает нюансы. Но если человек пишет на Vue и не может на коленке написать простой observable, не понимает как работает трекинг зависимостей… И при этом претендует на "хочу много много денег", то мы пожелаем ему удачи в другом месте.


                                                              Если человек пишет на React и не знает его основ (как работают props, context, зачем нужны key, что такое мемоизация и пр.), то ему будет ну прямо очень сложно у нас.


                                                              При этом сам фреймворк вторичен. Главное чтобы голова работала.


                                                              А как устроена ваша любимая игрушка (ну шейдеры там) вы знаете?

                                                              Не понял причём тут мы и игрушки. Но уверен, что нанимаясь на должность senior C++ game developer вы будете вынуждены отвечать на целый ворох вопросов из области 3D. В том числе и вопросы по шейдерам.

                                                                0
                                                                Но если человек пишет на Vue и не может на коленке написать простой observable, не понимает как работает трекинг зависимостей…

                                                                Ну в этом за день можно разобраться )
                                                                Если понадобится...


                                                                При этом сам фреймворк вторичен. Главное чтобы голова работала.

                                                                true, я думал вы просто "пшел нах" на ответ "если надо разберусь" говорите )


                                                                Не понял причём тут мы и игрушки.

                                                                Ну это такой "пирует" был, типа "фреймворк как игрушка" )

                                                          0
                                                          1. Селекторы и мемоизация — это про работу с иммутабельным состоянием, так ведь? А разве в vue так нельзя сделать? Ну, то есть не полагаться на observableArray вообще, а всегда возращать новый инстанс массива, с новыми инстансом студента внутри (если студента отредактировали). (Я про vue почти ничего не знаю — допускаю, что мой вопрос звучит наивно)


                                                          2. Ваш пример со студентами — computed же ведь и правда зависит от каждого студента, а не только от самого массива. Если сделать students[1234].age = 19, массив не поменялся, но computed все равно надо пересчитать. Или я опять что-то не так понял?


                                                            0
                                                            1. Селекторы и мемоизация это бич React-а. Типовое решение (но есть альтернативы в виде mobX к примеру). Но когда берёшь observable модель, последнее что хочется делать, это писать велосипеды с мемоизацией и селекторами :) Понятно, что уходя от Vue в деле бизнес-логики можно её переписать на что угодно и какой-угодно изолентой подцепить к Vue componentTree. Но какой смысл? Оставляя за Vue только роль шаблонизатора?
                                                            2. Проблема не в пересчёте. Если students[1234].age меняется, то и computed значение основанное на нём разумеется тоже должно обновиться. И Vue2 его обновит. Проблема в том, что Vue2 не способен даже считать уже закешированное значение без копирования абсолютно всех его зависимостей. Там где продвинутые (или лучше сказать "нормальные"?) observable решения просто запишут b зависит от a, где a зависит от 5000 других значений, vue2 запишет ему эти зависимости напрямую. А учитывая что во Vue2 буквально все bind-ы это тоже computed, то мы оказываемся в ситуации что любой render заставляет CPU 99% времени копировать зависимости. Фактически программа больше ничем не занимается кроме как копированием зависимостей.

                                                            И да. Я уже выше писал, что это можно обойти, например, отказавшись от computed и руками разрулив всё через watch-еры. Или отказавшись от Vue observables в пользу каких-нибудь более продуманных. Например затащить в проект RxJS или MobX. Да или то же самое решение с reselect, что я в итоге написал для React + Redux. Но зачем? Что такого ценного во Vue остаётся, чтобы это того стоило?

                                                              +1
                                                              1. спасибо за пояснение. полностью согласен
                                                              2. ага, я неправильно понял пример. перешел по ссылке на codesandbox, поигрался. действительно, выглядит очень странно и даже контринтуитивно.
                                                                +1
                                                                Очень хорошая ветка. Но есть нюансы:
                                                                Вычисления computed кэшируются и перевычисляются только при реальном изменении зависимостей. Вот небольшой пример: jsfiddle.net/hz2adcrn/1
                                                                А от лишних observables выручает object.freeze (и про это есть в документации почти в самом начале: ru.vuejs.org/v2/guide/instance.html#%D0%94%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D1%8B :) ).

                                                                И да, у меня был проект, в котором выводился график посещаемости для сотни сотрудников за пару лет работы с фильтрами и прочим на основе данных из СКУД. Там сильно больше 5000 объектов в исходных данных было. И computed перестали тормозить, как только я заморозил сырые данные (и данные проходов, и остальная неизменяемая НСИ, загруженная с бэкэнда). При этом все computed продолжали вычисляться — ведь в зависимостях у них остались значения фильтров.
                                                                Если же 5000 строк «глубоких» объектов надо менять, то тут надо действительно что-то придумывать, но ничего сильно костыльного не будет.
                                                                  0
                                                                  Если же 5000 строк «глубоких» объектов надо менять, то тут надо действительно что-то придумывать, но ничего сильно костыльного не будет.

                                                                  Имхо это вопрос дефиниции костыля :)


                                                                  Нужно будет на всех уровнях где большой список зависимостей рвать этот список. Например watcher-ами. А это дополнительный слой асинхронщины, там где её не ждёшь. Может вылиться во что-нибудь неприятное, вроде неконсистентного рендера. Ну и попахивает такой код, если честно. Вместо очевидного древа вычислений чуть ли не ручное указание зависимостей (тут завуалированный пинок в сторону React, которые своими хуками заставляет это делать).


                                                                  Про freeze спасибо. Полагаю, что 2 года назад этого ещё не было, т.к. все мои поиски приводили к стороннему плагину, которые, наверное, делал что-то подобное но "на свой страх и риск".


                                                                  Правда вот тут я уже начинаю плыть в вопросе организации подписки на изменение отдельных элементов массива (не их полей, а именно самих элементов, скажем students[123]. Скажем данные студентов можно менять иммутабельно (нечто вроде Vue.set(students, 1234, { ...student, age: newAge }). Но нужно ещё организовать точечные обновления компонент, которые завязаны на данные полей студента. Т.е. условно передав <StudentLabel v-bind:student={student[1234]}/>, я хочу чтобы оно само догадалось обновиться если student[1234] изменился. Но я не помню как точно работает передача props во Vue2. Оно сравнит их по === и в случае несоответствия принудительно перерендерит <StudenLabel/>? Или оно вообще всегда будет это делать, ничего не проверяя?

                                                                    0
                                                                    При этом все computed продолжали вычисляться — ведь в зависимостях у них остались значения фильтров.

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

                                                                      0
                                                                      Ну, тут можно пересчитывать все однократно, если сделать this.data = Object.freeze(modifiedData), то все однократно пересчитается, при этом лишних обзерверов не будет. Но при использовании vuex оно примерно так и будет само. Ну еще можно заменить массив на объект с ключами вместо бывших индексов, чтобы пересчет был не при изменении любого элемента, а только по цепочке от нужного. Кстати, вроде в vue3 это поправили. Много разных способов есть, нужный зависит от контекста задачи.
                                                                      Только для тоталов это не очень поможет, там все равно придется отвязывать зависимости, чтобы лишних циклов не плодить, а сделать "- старое значение + новое значение". Но я ни одной либы не знаю, в которой этот вопрос нормально сделан. В любом случае порог, до которого можно не заниматься оптимизацией в vue достаточно высок. При этом даже самые тривиальные приемы оптимизации (как выше) дают существенный эффект при использовании в узких местах.
                                                                        0

                                                                        Если я вас понял, то получается примерно та же самая схема, что была бы в случае redux + reselect (1 реактивная переменная + иммутабельность + ререндер почти всего, почти всегда).


                                                                        Рискну предположить, что на KnockoutJS и RxJS оно бы завелось без каких-бы то ни было приседаний. Просто решение в лоб. Но точно сказать не могу, т.к. времени поиграться не было.

                                                                          0
                                                                          В vue ререндер идет только у узлов, соджержащих реально изменившиеся данные, так что даже полный пересчет сильно легче. На сам DOM нагрузка минимальная. Это поведение сильно снижает головную боль по сравнению с тем же реактом.
                                                                            +1
                                                                            В vue ререндер идет только у узлов, соджержащих реально изменившиеся данные

                                                                            ЕМНИП то разница там такая:


                                                                            • React просто вызывает метод-компонент целиком и получает vDOM древо, которое затем реконсилирует. Разницу накатывает в DOM.
                                                                            • Vue ahead-of-time компилирует render метод сам, и выдаёт там следующую оптимизацию — выносит статические вещи наружу, тем самым обеспечив им неизменность по ===, что часто уменьшает глубину проверки во время реконсиляции

                                                                            Т.е. они делают практически одно и то же, но у Vue есть небольшой козырь в рукаве. Не думаю что это сильно что-то меняет. Или сейчас всё иначе работает?


                                                                            Точечные обновления делают Svelte и KnockoutJS. Вот про них действительно можно сказать, что "ререндер идет только у узлов, соджержащих реально изменившиеся данные". Без всяких "но" :) Ибо там никакого virtualDom под капотом нет и не планировалось.


                                                                            В описываемой ситуации я не вижу существенной разницы между количеством работы, которое сделает React и какое сделать Vue. И там и там оба framework-а будут рендерить свои vDom деревья целиком, во всех связанных и не связанных местах. И там и там будет запущена реконсиляция. И там и там по её результатам будут произведены нужные модификации DOM. Просто Vue не будет трогать совсем уж лишние ноды, которые умный компилятор вынесет в константы. Я прав?

                                                                              0
                                                                              Просто Vue не будет трогать совсем уж лишние ноды
                                                                              Просто Vue не будет трогать лишние ноды. Если понимать под лишними неизменившиеся ноды. Добавка «совсем уж» не понятно откуда.
                                                                                0

                                                                                "Совсем уж" — ноды у которых нет v-*. React будет их проверять, а Vue не будет. В этом разница. Поэтому добавка. Правда есть плагины для babel, которые делают почти ту же самую оптимизацию, что и компилятор Vue. Я с ними пока не игрался.


                                                                                В остальном поведение, полагаю, идентичное с React. Vue вызывает render метод, в котором остались тоьлко ноды с v-*. Vue сверяет их с предыдущим vDom-древом на предмет различий. Vue накатывает различия на реальный dom.


                                                                                Т.е. если говорить про vDom, то Vue будет трогать неизменившиеся ноды, т.к. он не знает о том, что изменилось, а что нет. Если горовить про браузерный dom, то Vue не будет трогать те ноды, в которых нет различий. В этом и суть virtualDOM. Впрочем Preact раньше (возможно и сейчас) обходится без промеуточных прослоек и сразу реконсилирует реальный DOM.

                                                                                  0
                                                                                  vue не будет вызывать рендер компонентов, которые не зависят от изменившихся данных. Из-за этого есть (были в версии 2) некоторые неудобства, например важность :key, но это все мелочи. В реакте решение простое — не использовать фичу, а использовать редакс, мобикс, вот хуки с недавнего времени появились, которые решают в т.ч. эту проблему :)
                                                                                  Просто в vue это было с самого начала (условного. в v2 точно было, а v1 я не использовал).
                                                                                    0
                                                                                    habr.com/ru/company/plarium/blog/426197 не бывает в принципе.

                                                                                    vue не будет вызывать рендер компонентов, которые не зависят от изменившихся данных.

                                                                                    React.memo


                                                                                    В реакте решение простое — не использовать фичу, а использовать редакс

                                                                                    Redux тут совсем не причём, если честно. Он решает проблему props.hell, а не проблему перерисовки нетронутых компонент. И да он тоже использует react.memo под капотом

                                                                                      0
                                                                                      React.memo
                                                                                      Это про результат вызова, а не про его отсутствие :)
                                                                                      Но да, грубо говоря, решает ту же задачу.
                                                                                      Redux тут совсем не причём, если честно. Он решает проблему props.hell
                                                                                      Ну так ничего не мешает ему решать более одной проблемы. Хотя действительно. Хотя я сейчас прикинул — он вполне может и не решать упоминаемой проблемы.
                                                                                    0
                                                                                    «Совсем уж» — ноды у которых нет v-*. React будет их проверять, а Vue не будет. В этом разница.
                                                                                    Про ноды у которых нет v-* мы даже и не говорим. Он не будет трогать ререндерить и те v-* которые зависят от неизменившихся данных.

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

                                                                                      Кажется причина вашего недовольства кроется в том что я разделяю рендер vDom древа и реального дом древа, а вы нет. Отсюда и непонимание.

                                                                                        0
                                                                                        ЕМНИП для тех компонентов, которые не зависят от измененных данных, в принципе не вызывается перерендеринг.
                                                                                          0
                                                                                          ЕМНИП для тех компонентов, которые не зависят от измененных данных, в принципе не вызывается перерендеринг.

                                                                                          Не готов утверждать это наверняка, т.к. не пишу на Vue, но скорее всего так и есть. Зачем рендерить вложеные компоненты, props-ы которых не изменились. React так делает по-умолчанию, за что его многие не любят. Тот самый React.memo как раз для того чтобы этого не делать и введён.


                                                                                          Интересно будет взглянуть как обстоят дела во Vue3 и хуками. Т.к. природа функциональных компонент добавляет очень много проблем, и если Vue3 тоже взял себе их на вооружение, то они должны были придумать какой-нибудь свой useCallback или иную альтернативу.

                                                                                        0
                                                                                        Он не будет ререндерить и те v-* которые зависят от неизменившихся данных.

                                                                                        Будет.


                                                                                        Вроде бы не должно быть двойственного толкования.

                                                                                        Должно.


                                                                                        var render = function () {
                                                                                            var _vm = this;
                                                                                            var _h = _vm.$createElement;
                                                                                            var _c = _vm._self._c || _h;
                                                                                            return _c(
                                                                                              "div",
                                                                                              { attrs: { id: "app" } },
                                                                                              [
                                                                                                _c("img", {
                                                                                                  attrs: {
                                                                                                    alt: "Vue logo",
                                                                                                    src: require("./assets/logo.png"),
                                                                                                    width: "25%",
                                                                                                  },
                                                                                                }),
                                                                                                _c("HelloWorld", { attrs: { msg: _vm.test() } }),
                                                                                              ],
                                                                                              1
                                                                                            );
                                                                                          };

                                                                                        Вот так ^ выглядит render метод вот этого:


                                                                                        <template>
                                                                                          <div id="app">
                                                                                            <img alt="Vue logo" src="./assets/logo.png" width="25%">
                                                                                            <HelloWorld v-bind:msg="test()"/> 
                                                                                          </div>
                                                                                        </template>

                                                                                        _c это аналог React.createElement. Часто это называют pragma-ой. Render метод возвращает новое vDom древо с каждым рендером. Всегда. Без исключения. А потом сравнивает между собой старое и новое древо. Найдя отличия Vue накатывает их на браузерный DOM. Точно так же работает React и другие реактивные библиотеки\фреймворки с virtual dom под капотом.


                                                                                        Поэтому тут 2 рендера:


                                                                                        • рендер vDom tree (вызов .render())
                                                                                        • рендер наживую в браузерном DOM-е (.appendChild, .remove, .insertAdjacentHTML, setAttribute и пр.)

                                                                                        Первый легковесный, второй тяжёлый. 1-ый вызывает 2-й. 2-й должен быть предельно производительным. 1-ый же туп как пробка — рендерит всё и всегда (в рамках своего компонента). Речь выше идёт про 1-ый.


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


                                                                                        Искренне надеюсь, что теперь у вас есть "двойное толкование". И интерес к тому, что на самом деле творится под капотом Vue.

                                                                                          0
                                                                                          Про «рендер наживую в браузерном DOM» все ясно, отложим его.
                                                                                          Давайте говорить о 1-ом — «рендер vDom tree (вызов .render())», Вы говорите,
                                                                                          что 1-ый же туп как пробка — рендерит всё и всегда (в рамках своего компонента).


                                                                                          а вот такая картинка по моему вам противочречит:
                                                                                          image
                                                                                          как я понимаю — при изменении данных вызывается ререндер только данного компонента в Virtual DOM. Вы думаете, что при изменении ререндятся все компоненты в рамках своего компонента, что на мой взгляд не верно.
                                                                                            0
                                                                                            как я понимаю — при изменении данных вызывается ререндер только данного компонента в Virtual DOM

                                                                                            Это никак не противоречит ничему что я сказал выше


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

                                                                                            Проблема тут только в том, что я так не думаю :)


                                                                                            vDomNode и Component это разные понятия. К примеру вот так выглядит типичная React vDomNode:


                                                                                            const reactVDomNode = {
                                                                                              $$typeof: Symbol(react.element),
                                                                                              key: null,
                                                                                              props: { children: '123' },
                                                                                              ref: null,
                                                                                              type: 'b',
                                                                                              _owner: null,
                                                                                              _store: { validated: false },
                                                                                              _self: null,
                                                                                              _source: null,
                                                                                            };

                                                                                            Похожим образом выглядит и Vue2 virtual dom node. Это просто небольшой объект, который содержит:


                                                                                            • тип ноды (ссылку на компонент или имя тега)
                                                                                            • её props-ы

                                                                                            В общем это всё вопрос терминологии. Всё самое интересное в вашей картинке зарыто слева. Там где жёлтый круг, стрелка вниз и дерево.

                                                                                    0
                                                                                    Речь не только про это. А про то, что в компонентах хранятся зависимости и ситуации как в habr.com/ru/company/plarium/blog/426197 не бывает в принципе.
                                            +1

                                            На react можно spread в пропсах использовать. В vue2 это недоступно, в анонсах vue3 не вижу.

                                              0
                                              Если я правильно понял, это делается как-то так (vue2): gist.github.com/FragsterAt/bd5dba77245db1cd4c6896ff78a9b7c6 Это микрокомпонент с дефолтными значениями для компонента из фреймворка. На самом деле в данном случае v-bind и v-on не нужны. А вот если надо не на корень их навесить — тогда да.
                                                0

                                                Хм. По примеру непонятно как это связано с:


                                                <div {...someProps} someOtherProps={1} />

                                                во Vue2 & Vue3 так можно? Эта штука очень плотно используется в реальном React коде. Особенно с TS.

                                                  0
                                                  В примере прям оно и есть: ru.vuejs.org/v2/api/#v-bind, ru.vuejs.org/v2/api/#vm-attrs, spread внутри (как и любой js, включая вызов функций) работает. Прям эквивалентом является:
                                                  <div v-bind="someProps" :someOtherProps="1" />
                                                    –1

                                                    Всё равно ничего не понятно. Вы просто вынесли все props из someProps в какую-то отдельную wrapper сущность со слотом? Really? Где явным образом всё равно всё перечисляете, указывая default и типы? А зачем оно такое кому-нибудь нужно?

                                                      +1
                                                      В моем примере передаются все входные параметры далее во вложенный компонент. Плюс ещё два, для которых я задал дефолтное значение, отличающееся от дефолтного значения компонента, который вложен в мой компонент. Если же на входе будет color и size, то они также попадут во вложенный компонент, для него ничего не изменится.

                                                      Входящие данные компонента можно рассматривать как объект. Если ключ объекта есть в секции props, то значение попадает в соответствующее поле (доступное в this и в this.$props), остальное — попадает в this.$attrs. И с этими данными можно работать. v-bind без параметра принимает на вход объект, ключи которого переносятся в свойства элемента.
                                                      <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
                                                      является эквивалентом
                                                      <div v-bind:id="someProp" v-bind:other-attr="otherProp"></div>
                                                      ну, или в сокращенном синтаксисе:
                                                      <div :id="someProp" :other-attr="otherProp"></div>

                                                        0

                                                        Ааа. То есть код в вашем gist-е это не пример ..., а просто пример компонента? Я думал это часть решения для ....


                                                        Т.е. фактически получается что v-bind="anyPropsObject" это аналог {...anyPropsObject}?


                                                        И для <A {...propsPack1} {...propsPack2} otherProp={4}/> нужно написать <A v-bind="{ ...propsPack1, ...propsPack2 }" v-bind:otherProp="otherProp"/>?


                                                        Если всё так и больше ничего нигде велосипедить не нужно (к примеру внутри компонента, или создавая над ним обёртку), то вполне юзабельно.


                                                        Правда в случае TS и React, тут ещё срабатывает проверка типов и если propsPack1 или propsPack2 содержат некорректные данные, то оно не скомпилируется. Ну и как вишенка на торте, если указать что-нибудь типа:
                                                        <A otherProp={1} {...props}/> где type Props = { a: number } мы получим warning, о том, что otherProp={1} бесмысленно, т.к. всегда перезаписывается.

                                                          +1
                                                          фактически получается что v-bind="anyPropsObject" это аналог {...anyPropsObject}?
                                                          Да
                                                          для <A {...propsPack1} {...propsPack2} otherProp={4}/> нужно написать <A v-bind="{ ...propsPack1, ...propsPack2 }" v-bind:otherProp="otherProp"/>
                                                          Да, только v-bind:otherProp="4"
                                                          TS и React, тут ещё срабатывает проверка типов и если propsPack1 или propsPack2 содержат некорректные данные, то оно не скомпилируется
                                                          Напрямую в шаблонах проверки типов ts нет, есть консольная версия vti (см ветку habr.com/ru/post/520022/#comment_22094558 ), которая проверяет типы в шаблонах. На досуге посмотрю, как она на это реагирует.
                                          0
                                          Уже на rc версиях перевез два проекта и две библиотеки без проблем.
                                            0
                                            ups
                                              0
                                              Vue становится ближе к Svelte
                                                0
                                                Изучая мануал наткнулся на новую интересную фичу «телепорт»
                                                  0
                                                  Это чем-то похоже на vue-portal

                                                Only users with full accounts can post comments. Log in, please.