Pull to refresh

Comments 41

Это крик души? Тогда максимум сострадания)

Крик, но уже переходящий в хрип)

Да не плачьте :) Дело не в Vue. Просто так сложилось, что react был раньше, c 2011, поддерживался крупной компанией со старта, было больше написано инструментов, фреймворков. Вот и получается, что в крупных проектах, чаще используются либо angular либо react. Проще найти специалистов, проще найти библиотеки с лучшей поддержкой, больше комьюнити, больше нейронов в ИИ моделях натренированных на react.

Крутость уже не играет роли, можно на любом языке написать с ошибками. И смысл тогда?

React.js vs. Vue.js
Linux vs Minix
Rust vs. C++
...

Я вообще как бекенд разраб тайно люблю Svelte. Но грущю об этом исчезающе редко)

Sveltekit, но они о нём даже не слышали

Vue берёт лучшее из всех миров)

И в одну сторону со Svelte в том числе тоже смотрит. В последней версии появился экспериментальный (пока) Vapor Mode.

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

Почему это? Я возьму <Outlet />

Наконец кто-то это сказал)))

Я говорил это с 2021, времен vuejs2/nuxt2. А потом, с середины 2025, мне стало все равно. Хотя стоит отметить, что предпоследней мажор nuxt4 хорош, а 5 будет ещё лучше.

Я тоже устал от реакта и его костылей. И я тоже высказался - записал видео на Ютуб: реакт vs vue. Набежали макаки реактовские и начали мне писать про правильную декомпозицию

Понимаю))

Я тоже в свободное время глубоко копаю и React, и Vue, и последние наблюдения заставляют задуматься. В экосистеме React, например, до сих пор нет прямого аналога Quasar «всё в одном». С React Compiler тоже были шероховатости в пет-проектах: в связке с react-hook-form иногда ломался ререндер :(

В React начиная с версии 19.2 доступен компонент <Activity>, функция которого насколько я понимаю такая же, как у <KeepAlive> из Vue.

А что предлагает Vue в качестве альтернативы реактовским useTransition / useDeferredValue?

useTransition is a React Hook that lets you render a part of the UI in the background.

useDeferredValue is a React Hook that lets you defer updating a part of the UI.

Насколько я понял из документации, это специфичные для react хуки. Реактивность vue из коробки позволяет обновлять “part of the UI”, обновляя только компоненты которые реально изменились

В основе Vue так же как и в основе React лежит концепция Virtual DOM, и, насколько я могу судить, так же как и в React компоненты обновляются целыми деревьями начиная от того компонента, где произошло изменение состояния. Поэтому проблемы, которые решают useTransition и useDeferredValue в React, ровно в той же степени актуальны и для Vue.

В моей карьере случаев, когда приходилось пользоваться этими хуками, было не так уж и много, но каждый раз я радовался тому, что работаю с React, а не другим фреймворком, потому что иначе пришлось бы пользоваться костылями вроде предложенного здесь варианта с useDebounceFn: https://dev.to/jacobandrewsky/handling-large-lists-efficiently-in-vue-3-4im1

Если надо, могу объяснить, почему это даже близко не то же самое.

Насколько мне известно, похожих на useTransition / useDeferredValue механизмов нет ни в одном другом фреймворке кроме React, и одного лишь этого факта мне уже достаточно для того, чтобы считать React более пригодным для по-настоящему сложных приложений, чем какое бы то ни было иное решение.

Если надо, могу объяснить, почему это даже близко не то же самое.

Да, будьте добры, потому что из того что я вижу (не работал с реактом) это прям что-то узконаправленное под рендер реакта. Вообще, useTransition очень похож на nextTick, а useDeferredValue очень похож на дебаунсер с тем отличием, что он срабатывает не через “фикс” время, а когда откроется окошко для обновлений. Оба очень похожи на requestIdleCallback.

Ни nextTick, ни requestIdleCallback, ни setTimeout, ни что-либо ещё в от природы своей однопоточном джаваскрипте не способно прервать выполнение синхронного кода. Вот пример, который позволяет в этом убедиться:

setTimeout(() => console.log('a second passed'), 1000);
for (let i = 0; i < 1e10; i++);
console.log('for loop done');

Хоть мы и запросили вывод строки “a second passed” через секунду, на деле выводится она лишь после того, как завершается выполнение цикла for, а это происходит намного позже. Связано это с тем, что цикл выполняется синхронно, то есть не уступая дорогу никакому другому коду, пока цикл не будет выполнен полностью.

По той же самой причине строка “for loop done” появляется в консоли перед “a second passed”, хотя на момент её вывода прошло уже сильно больше одной секунды. Никакой код не может влезть ни между итерациями цикла, ни между циклом и выводом “a second passed”. Всё это синхронный код — последовательность выполняемых друг за другом инструкций, и возможности прервать его просто не существует. Чтобы такая возможность была, код надо сделать асинхронным, например вот так:

function tick() {
  return new Promise((resolve) => setTimeout(resolve, 0));
}

setTimeout(() => console.log('a second passed'), 1000);

let i = 0;
for (let j = 0; j < 1e3; j++) {
  const end = i + 1e7;
  for (; i < end; i++);
  await tick();
}

console.log('for loop done');

Вычисление здесь мы разделили на 1000 равных по продолжительности частей, в конце каждой из которых с помощью await tick() контроль передаётся циклу событий (event loop), который продолжает выполнение цикла for лишь после того, как будут выполнены все остальные ждущие в очереди задачи. Примером такой задачи может быть выполнение переданной setTimeout функции по истечении указанного срока (в нашем случае это вывод строки “a second passed” по прошествии одной секунды). Другой пример — считывание взаимодействий пользователя со страницей, которые прежде были полностью заблокированы на время вычисления цикла for. Если запустите сначала первый, а потом второй пример в консоли браузера и во время вычисления попробуете нажать куда-нибудь или ввести текст на странице, к которой эта консоль привязана, разница будет очевидна.

Теперь наконец можем вернуться к useTransition и useDeferredValue. Весь смысл этих хуков в том, что они превращают изначально синхронную операцию рендеринга дерева компонентов в асинхронную так же, как это было проделано мной с циклом for в примере выше. Оба хука позволяют выполнять тяжеловесные обновления UI на фоне таким образом, чтобы это никак не мешало более срочным синхронным обновлениям и взаимодействию пользователя со страницей, а useDeferredValue ещё и позволяет отменять обновления, которые становятся неактуальны из-за изменившихся вводных данных — например когда пользователь быстро вбивает слово в строку поиска, чтобы отфильтровать по нему данные в таблице. Это как раз тот самый пример, где Vue разработчикам предлагается использовать useDebounceFn. Преимущество useDeferredValue по-моему довольно очевидно:

В случае useDebounceFn фильтрация происходит лишь после того, как ввод слова в строку поиска был завершён (например по прошествии 300 мс с момента ввода последнего символа). Из-за этого фильтрация всегда ощущается заторможенной вне зависимости от размера таблицы.

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

Насчёт узконаправленности хуков под рендер реакта: я не думаю, что это соответствует действительности. Возможность прервать рендеринг имхо должна быть во всех фронтенд-фреймворках, поскольку в каждом из них возможна ситуация, когда рендеринг занимает дольше 1000/60 = 16,67 мс, и таким образом в случае его синхронности страница начинает ощущаться заторможенной, как если бы показатель FPS упал ниже 60 кадров в секунду. Но по какой-то причине в то время как разработчики React задумались над решением этой проблемы ещё 10 лет назад (о чём подробнее рассказано в этом отличном видео: https://youtu.be/edN42P_vfCI), другие фреймворки по сей день не считают её приоритетной.

Чтобы такая возможность была, код надо сделать асинхронным, например вот так:

Я бы сделал так:

setTimeout(() => console.log(a second passed'), 1000);

function* heavyProcessGenerator(totalIterations) {

  const chunkSize = 1e10;

  for (let i = 0; i < totalIterations; i += chunkSize) {

    const end = Math.min(i + chunkSize, totalIterations);

    for (let j = i; j < end; j++) {

    }

    yield i;

  }

}

function runGenerator(iterator) {

  function step() {

    const result = iterator.next();

    if (!result.done) {

      setTimeout(step, 0);

    } else {

      console.log('for loop done');

    }

  }

  step();

}

runGenerator(heavyProcessGenerator(1e10));


При желании можно и на vue написать кастомный хук с соответствующим функционалом "магических" хуков реакта (наверное), чтобы не только React считать

более пригодным для по-настоящему сложных приложений

В том-то и прикол, что нельзя на Vue ничего такого написать, потому что рендеринг там заведомо синхронная операция. Эта идея обречена на провал, так же как и попытки найти способ вмешаться в цикл for из моего первого примера. Чтобы его можно было прервать, он изначально должен быть реализован таким образом, который позволил бы это сделать, но это, увы, не так. Та же ситуация и с рендерингом во Vue.

Это да. Но во vue ты можешь управлять сам моментом начала рендера чего-то тяжёлого. Смысл тот же, но просто ты сам выносишь планировщик рендера наружу из системы реактивности:

import { ref, watch, nextTick } from ‘vue’;

function useDeferredValue(value, delay = 100) {

const deferredValue = ref(value.value);

watch(value, (newVal) => {

setTimeout(() => { deferredValue.value = newVal; }, delay); });

return deferredValue;

}

Но в реальной разработке на vue это требуется редко. В отличие от React, где при изменении стейта пересчитывается весь Virtual DOM компонента, система реактивности Vue (Dependency Tracking) обновляет только конкретные DOM-узлы, затронутые изменением. Поэтому там, где в React нужно либо прерывать рендер (Concurrent Mode), либо вручную оборачивать всё в useMemo/React.memo, во Vue обновления просто происходят быстрее и точечнее, не блокируя интерфейс.

компоненты обновляются целыми деревьями начиная от того компонента, где произошло изменение состояния

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

Activity работает через display: none, это даже не близко KeepAlive. Это не масштабируется на десятки экранов.

Забавно, что они 3 года пилили этот Activity, а получилось такое Г.

Преимущество подхода с display: none в том, что помимо состояния, контролируемого React, сохраняется также и неконтролируемое состояние вроде значений <input>'ов и времени, на котором было остановлено проигрывание видео. Оба этих примера приведены в документации:

https://react.dev/reference/react/Activity#restoring-the-dom-of-hidden-components

https://react.dev/reference/react/Activity#my-hidden-components-have-unwanted-side-effects

Логики в этом по-моему больше, чем в сохранении лишь той части состояния, которая контролируется фреймворком.

В ролике не объясняется, каким образом удалось достичь сохранения DOM состояния. Предположу, что это было сделано за счёт сохранения DOM узла в памяти после его удаления из дерева документа с помощью removeChild() / remove(), чтобы потом этот же узел можно было добавить обратно. Других способов полностью сохранить DOM состояние я не знаю.

Так или иначе, узел со всеми его подузлами должен оставаться в памяти, и поэтому мне совсем непонятно, с какой это стати такой подход лучше масштабируется. По-моему вся разница между ним и подходом команды React с display: none сводится к тому, видно ли скрытые узлы в инструментах разработчика. Сказать, что эта разница сильно влияет на масштабируемость, было бы нехилым таким преувеличением.

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

Когда я говорю про масштабирование я в первую очередь имею в виду простоту и удобство использования.

Когда мы переводили проект с Twig на современный frontend, то как у многих встал выбор между React и Vue. И на тот момент для меня killer feature стало то, что переход на Vue можно было делать постепенно. И на надо было сразу писать ВСЁ на Vue/React, параллельно поддерживая еще и новые изменения в ветке с Twig. У нас банально не было столько ресурсов на это. Мы обернули весь проект во Vue, внутри всё так же работал Twig. А потом начали рефакторинг Twig -> Vue шаг за шагом, компонент за компонентом. И это был рабочий план. Потом я познакомился с Composition API, ref-сами, Pinia. И да, сейчас Vue на голову превосходит React, и все новые проекты я делают только на Vue, потому что для себя я определил, что это правильныы путь.

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

Пишу на vue, react не трогала уже лет двенадцать точно, поэтому не знаю даже уже, что там.

Но во vue не всё так безоблачно, как описываете. Проблема с зоопарком непонятных пакетов тоже есть. Хвалёный Quasar обладает такими недостатками, что использовать его на практике не получается.

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

Но вы говорите, что в реакте всё ещё хуже. Тогда действительно непонятно, почему за него держатся.

Когда-то очень давно меня впечатлило, что во vue есть v-model, когда в реакте для двусторонней связи нужно было серьёзные пляски исполнить. Но это было давно. Версия реакта была что-то вроде 0.15. Как сейчас — не знаю

React и Vue - тут выбор скорее зависит не от фреймворка, а от команды и рынка. Оба хороши и удобны, огромное количество отличный библиотек для каждого из них.

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

Для создания сложных приложений IMO Angular - React я всегда рассматривал наоборот для каких-то мелких приложений где не нужна серьезная архитектура/структурированность. Но даже для легких приложений я как Angular based разработчик всегда выбирал Vue. Он в разы чище, структурнее и с ним проще работать.

Боже как я тебя понимаю)
тоже самое говорят и про $mol

Такой тред, а поклонников моли до сих пор нет... Не дорабатывают

А вообще во вью забивают на jsx и пушат шаблоны уровня пуга или как он там сейчас называется. Одно это отваживает меня от вуя (да, у меня птср от хамл, пуга и подобного мусора). Ну и по мелочи там, опуская малый процент рынка и слава б.гу — мне и реактов со свифтами и некстами хватает, fine-grained reactivity влечёт держание в уме работу с рефами\reactive, toRefs добавляет масла; composition api переусложнён; реакт без пробелм на тс ложится, в вуе пляску с бубном помню с его definedProps<T>() или как там; вместо единой линии партии зопарк какой-то из options api, composition api, script setup, миксинов и ещё чёрт знает чего; про RSC вообще молчу. Впрочем, это больше вкусовщина и сейчас действительно можно писать на нём.

А про "серьёзное и несерьёзное" это наверное больше говорят в контексте что в вуе очень низкий порог входа?

Алсо, про кипалайв. Можно набросить что он для quick&dirty решений, когда же реакт толкает к арзитектуре с разделением на состояние и юи + не жрёт ресурсы пока поддерево заморожено (у вуя вроде тоже можно так сделать, но надо ручками всё чистить). Люди и так воют на ужасного веб-пожирателя ресурсов, а вуй,получается, ещё больше усугубляет эту проблему хд. Ну и не спорю что я вуй весьма поверхностно знаю, но вроде как кипалайв не даёт возможность пререндерить контент, например, когда в реакте можно сделать что-то типа <Activity mode={activeTab === 'home' ? 'visible' : 'hidden'}> и радоваться

А, и самое главное. На вуе нельзя писать под мобилки без головной боли. Шах и мат. С реактом ты можешь очень быстро расширить своё сознание до свифта с котлином и начать писать на рн, а с вуем... кхм, оказываешься запертым в психотронной веб-тюрьме (кто-то скажет про квазар, но забудет упомянуть что в мобилки он тащит вебвью, а для десктопа вообще хромога бггг)

keep-alive во Vue — это инструмент для кеширования состояния и экземпляров, он удаляет компоненты из DOM, освобождая ресурсы рендеринга.
То, что ты описываешь в React (Activity / hidden rendering) — это про пререндеринг. Во Vue это делается просто через v-showи это было под капотом с первых версий.
Что касается ресурсов: keep-alive хранит только JS-объект в памяти, а не живой DOM. Да, надо ручками чистить таймеры, подписки и тд, но это ответственность и дисциплина разраба писать чисто и убирать за собой)) Так что претензии к инструменту keep-alive тут беспочвенны)

Относительнл недавно остро встал вопрос на чём писать frontend не имея какого-либо опыта в современных фреймворках.

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

Выбирал очень долго. Angular я отмёл из-за typescript only (как я понял), а react из-за JSX (очень сильно напомнило JSP и сразу оттолкнуло, с меня хватит уже этого "дерьма").

Дошёл до Vue, сразу понравилась концепция где можно в одном файле компонента хранить разметку, код и стили. Для моих целей этот подход более удобен. Плюс поддержка как javascript, так и typescript. Я себе выбрал js, потом может перейду на ts, но это не точно. Ещё я познакомился с h() - моё почтение! JSX тут как мне кажется курит в сторонке.

Вместо вывода: я как бэкендер - кайфую от Vue! Реально удобный фреймворк. Оказалось, что создавать UI на современном стеке - это невероятно классно. С удовольствием погружаюсь с ним в создание нового компонента. И нисколько не жалею о выборе именно Vue. Для моих целей - он идеален.

Ооо да, сам так столкнулся. 5 лет на vue и последние полтора года на nuxt.

Такая история появилась где то пол года назад со второй работой, успешно весь фронт на nuxt с нуля поднимал, все отлично. Но тут в силу вступили требования, типа react это завод а nuxt/vue это так, экскаватор на радиоуправлении, и причем больше ссылаются что реакт это прям какое то божество которое можно крутить вертеть как хочешь. Покопался я в реакт коде и это такое усложнение как по мне, но людей не переубедить т.к. типа всякие lovable figma и другие на реакте выдают все.

Но те кто так говорят не могут мне ответить почему vue/nuxt хуже если все строится с нуля? Вот просто отказываются как либо комментировать данную вещь, но почему то команда которая сидит на vue/nuxt ничего плохого не говорила ни разу, разве что "неудобно как то".

Просто сейчас после простой архитектуры vue script/template реакт вообще не поддается какому либо пониманию)

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

Sign up to leave a comment.

Articles