Первый продакшн-проект на Vue после нескольких лет на React
Первый продакшн-проект на Vue после нескольких лет на React.
Базовые идеи в React и Vue очень похожи: компоненты, пропсы, стейт, lifecycle, слоты (они же children в React). Под разными терминами и синтаксисом скрываются схожие решения на одни и те же проблемы. По сути это две реализации одной идеи: React обновляет UI через ре-рендер компонента целиком, Vue точечно отслеживает зависимости и обновляет только то, что изменилось. Разница не в “что”, а в “как”.
Реактивность оказалась проще. В React есть useState для стейта и useMemo для производных значений, и надо явно перечислять зависимости в useEffect. Любая ошибка в указании зависимостей приводит к тому, что либо компонент не реагирует на изменения, либо уходит в бесконечный ре-рендер.
В Vue просто объявляешь computed(). Он сам отслеживает, от чего зависит, не нужно ничего перечислять. Это убирает целый класс ошибок, о которых просто перестаёшь думать.
// React
const total = useMemo(
() => items.reduce(sum, 0),
[items], // нужно явно указывать зависимости
);
// Vue
// отслеживается все изменения автоматически
const total = computed(() => items.value.reduce(sum, 0));
Раньше .vue-файлы казались мне неправильными: шаблон, скрипт и стили в одном файле, хотелось разнести их по разным местам.
Потом дошло, что в React я делаю то же самое. JSX это и разметка, и логика, CSS-in-JS добавляет ещё и стили. Просто привык и не замечал. В итоге разница только в синтаксисе и том, насколько это явно.
// React
<input value={name} onChange={(e) => setName(e.target.value)} />
<!-- Vue -->
<input v-model="name" />
// React
{
isLoading ? <Spinner /> : <Content />;
}
<!-- Vue -->
<Spinner v-if="isLoading" />
<content v-else />
Ещё вспомнилась непривычная особенность с onMounted. В React любая логика при маунте это useEffect(() => {}, []), уже на автопилоте. В Vue с <script setup> можно просто писать код на верхнем уровне: он выполнится в фазе setup, до рендера. onMounted нужен только когда реально нужен DOM. Поначалу казалось, что я что-то делаю неправильно.
// React
useEffect(() => {
fetchUser();
}, []); // не забудь []
// или будет бесконечный ре-рендер
// Vue (script setup)
fetchUser();
// просто пишешь здесь
// выполняется при setup
// хук не нужен
Реактивный стейт (ref, reactive, computed) в Vue можно вызывать условно. В React хуки зависят от порядка вызова, поэтому if (condition) { useState(...) } просто не работает. В Vue это ограничение снято.
В какой-то момент поймал себя на мысли, что пишу как будто на React, но с некоторыми изменениями. Если хорошо знаешь React, переход на Vue это неделя адаптации. Думаешь о коде примерно так же, просто инструменты называются по-другому и местами работают иначе.
← К статьям