Как говорил М.Т. Калашников: «Просто» сделать в 1000 раз сложнее, чем «сложно». Веб-индустрии понадобилось более половины десятилетия, чтобы прийти от фреймворков-монстров к простой и элегантной конструкции. В IT простота это не только сэкономленные часы работы, а ещё и прозрачная архитектура, выливающаяся в понятный код, меньшее число багов, более быстрое внесение изменений и много других приятных вещей.
В этой статье я проведу сравнение Vue.js с двумя наиболее популярными на данный момент фреймворками: Angular и React. Vue.js намного моложе, поэтому разговор будет прежде всего о нём, об Angular и React грамотные разработчики и так знают. И я бы не начинал этот разговор, если бы Vue не предлагал чего-то действительно стоящего. К счастью это так, и я утверждаю, что в большинстве случаев Vue.js может серьёзно снизить сложность ваших программ, сделать код более лаконичным и выразительным, а отладку — короче и проще. Подробности под катом. Поехали!
Если совсем кратко, то Vue.js — невероятно ненавязчивый фреймворк. Если Angular и React заставляют вас установить целый зоопарк зависимостей, то Vue в минимальной конфигурации не просит от вас абсолютно ничего, кроме собственного js-файла. За это он даёт custom controls, data binding, кастомные директивы и, фактически, все востребованные фишки основных фреймворков. Пример ненавязчивости:
Как выглядит простейшая программа на Vue
Достаточно просто подключить библиотеку, создать контейнер и вызвать конструктор, всё как в старом добром Angular 1, только без его тормозов:
<div id="app">{{ message }}</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
Это действительно весь код, который вам нужен, это не шутка. Вы можете прямо сейчас скопировать его в редактор, сохранить как something.html и он будет работать. Без плясок с бубном, dependency hell и прочих артефактов современности. Не буду рассказывать как то же самое делается в React или Angular 2+. Про то, как вытащить JSX из React или как писать без TypeScript на Angular 2+ можно написать целую статью.
Почему бы не оставить всё как естьЧем плох TypeScript? Хотя бы тем, что я его не заказывал. В 2005-м году мы боролись за каждый килобайт веса страницы, а сейчас сайты весят по 15 мегабайт и, как будто бы, так и нужно, но это неуважение к пользователю. Я не говорю, что в этом виноват TypeScript, или JSX, или 100500 других побочных технологий, но я хочу сам выбирать, что использовать, а что нет. И чтобы не пришлось платить за этот выбор часами на stackoverflow.
Что касается конкатенации и минификации кода, то для Vue доступно много решений с готовыми сборщиками на том же yeomen (например
github.com/birdgg/generator-vuejs), так же как и для React или Angular. Разница в том, что у вас есть право выбора, использовать их, не использовать, или самому создать сборщик под особенности конкретного проекта.
Custom Controls
Распространённый сценарий развития большинства веб-приложений — увеличение плотности функционала:
- у вас была обычная кнопка, а стала кнопка со индикатором состояния запроса
- была обычная таблица, а стала таблица с сортировкой и фильтрами
- было обычное меню, а стало меню с многократной вложенностью
Если такие компоненты встречаются в приложении один раз — ничего страшного, но чаще бывает, что они раскиданы по разным страницам и в большом количестве. Без custom control такие задачи решаются через боль, мучения и большие затраты времени, с custom controls это делается быстрее в несколько раз. Если вы не сталкивались с такой проблемой — значит у вас не было более-менее серьёзных проектов. Custom controls — это абсолютно must have в современном frontend-программировании. В Angular 1 custom controls отсутствовали (если не считать директивы, которые изначально предназначались совсем для других вещей). В Angular 2+ и React они есть, но достаются довольно дорого. Синтаксис Vue.js очень похож на Angular 2+, но без его ограничений. Немного модифицируем код, представленный выше:
<div id="app">
<ol>
<todo-item v-for="item in list" :todo="item"></todo-item>
</ol>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
});
new Vue({
el: '#app',
data: {
list: ['first item', 'second item']
}
});
</script>
Получилось чуть подлиннее, но у нас здесь custom controls. Custom controls в 20 строчках кода, Карл! При этом сам компонент занял всего 4 строчки. Что это значит на практике: что вы можете делить свой код на компоненты настолько мелко, насколько вам хочется, с минимальными издержками. Если в React создание отдельного компонента — целая история, в завязкой, кульминацией и развязкой, то в Vue это просто несколько секунд. И дело не в этих секундах, а в том, что с большим количеством компонентов у вас будут слабее зависимости и меньше багов.
Это синтетический пример компонента, но в реальных Vue.js раскрывает себя ещё лучше. Мы можем, например:
- вынести весь код компонента в отдельный *.vue файл, включая html, css и javascript
- использовать css-препроцессоры прямо в коде файле компонента, просто указав lang=«scss» или другое
- использовать любые глобальные объекты или получать объекты через import (в React, кажется, на это есть ограничения)
- использовать компоненты только внутри других определённых компонентов, без объявления в глобальной области видимости. Использовать компонент под другим именем, без изменения самого компонента (удобно в случае коллизии имён сторонних компонентов)
и многое другое. Для большинства этих функций нужно подключать сборщик (в документации описан webpack), однако вам дают выбор, использовать Vue на 10%, 50% или на все 100%. Плюс, на мой взгляд, они выбрали самый стабильный и прозрачный сборщик из существующих, но вы можете поменять и его. Вообще Vue поражает своей модульностью и слабосвязанностью, архитектура просто очень хорошо продуманна, что выливается в огромное удовольствие при работе с любой его составляющей. Например:
Создание своих плагинов
Перед тем, как открыть спойлер с кодом остановитесь на минутку и подумайте, как бы вы пропатчили незнакомую библиотеку, если бы захотели добавить туда новый кастомный метод. Подумали? Теперь открывайте ответ:
Как это делается в Vue.js Vue.prototype.$myMethod = function (methodOptions) {
// something logic ...
}
Vue.prototype, Карл! Вам даже не нужно знать
документацию, вы её и так знаете большую её часть на уровне подкорки. Больше никаких странных конфигов, магических свойств, которые нужно указать, чтобы всё заработало. Просто Vue.prototype и имя вашего метода, почему все фреймворки не используют это? Если хотите устанавливать плагин через Vue.use(MyPlugin), то нужно определить метод MyPlugin.install, но это, как и многое в Vue, по вашему желанию.
Общая обстановка
У меня есть большие претензии к команде Angular. Даже не побоюсь сказать, что они фактически убили Angular, создав два совершенно разных продукта и назвав их одним именем. Даже у Vue больше общего с Angular и 1 и 2, чем у этих версий между собой. Возникла огромная путаница в документации, которая ещё не скоро прекратится. Но дело даже не в этом, как гласит один из канонических принципов создания хорошего ПО: делайте программы открытыми для дополнения, и закрытыми для изменения. Подобные радикальные изменения API Angular говорят о том, что продукт изначально был создан проблемным, идеальные программы не нуждаются в изменениях (например /bin/true в linux не переписывалась с 1984 года :)). Конечно Angular это не /bin/true, но реформы — всегда признак проблем.
В чём же причина? Я думаю в том, что как React — это проект для внутренних нужд Facebook, так и Angular 2+ — это проект для внутренних нужд Google. Конкретной компании не требуется поддерживать универсальность. Зачем поддерживать ES6, если в самой компании пишут на TypeScript? Зачем отделять React от зависимостей, если внутри компании он без зависимостей не используется? Конечно пользователи просят, и иногда им идут на встречу, чтобы они совсем не отвернулись, но всё же главная задача этих проектов — не наше с вами счастье, а облегчение найма в эти компании, когда приходит новичёк и уже знает основной стек технологий. Но стек конкретной компании, пусть даже очень крутой, не может являться стандартом для всей отрасли. Отсюда все проблемы с Agular и React. Vue, насколько мне известно, напротив, создавался именно для сообщества, поэтому получился модульным, универсальным, легко адаптируемым под нужные задачи.
Философия JavaScript
Немного историиВ конце прошлого десятилетия начала набирать популярность концепция Rich Internet Applications, Single Page Application, всё больше программ стали перемещаться в «облако». Это породило огромный спрос на JavaScript программистов, и снизило спрос на программистов компилируемых языков, традиционно используемых для создания desktop-приложений. Большое количество программистов начали массово переучиваться с C++, C#, Delphi, Java на JavaScript. Это имело как положительные, так и отрицательные стороны. С одной стороны эти ребята обогатили JavaScript новыми архитектурными подходами, и JavaScript, как мультипарадигменный язык, всё благополучно принял. Но с другой, непонимание JavaScript и, часто, не желание его как следует понять, породили огромное количество костылей, которые начали раздавать и больным и здоровым. Через некоторое время часть здоровых решили, что ходить в костылями — это модно, и тоже начали их использовать. Дошло до того, что в ES5 костыли дошли до уровня стандартов, породив Object.freeze и Object.seal, которые не только противоречат тому, как исконно даются разрешения в JavaScript, но и работают медленнее. Ребята просто не знали, как контролировать свои объекты, вот и решили рубануть с плеча. К счастью с тех пор прошло много времени, они поднабрались опыта и силы добра начинают побеждать, и сделанный по всем best practices Vue.js тому живое подтверждение.
Ответьте на вопрос, зачем во frontend нужны модели? Какие функции они выполняют и какие к ним требования? Могу поспорить, что всё, кроме загрузки и сохранения состояния можно создать в JavaScript в два символа: "{}". Обычный объект JavaScript из коробки имеет геттеры и сеттеры, позволяет установить вотчеры на любое свойство и имеет столько функционала, что ни в сказке сказать, ни
пером описать. Тем не менее, каждый фреймворк считает своим долгом написать свой велосипед, как state в React или factory в Angular. Когда-то в 2012 в этом мог быть какой-то смысл (тоже спорный), но сегодня это просто атавизм. Тем не менее наши пользователи по прежнему продолжают платить за это дополнительным ожиданием и подтормаживаниями. Да, они небольшие, но это только один пример, а их сотни, следствие неправильного понимания философии JavaScript. В Vue тоже можно подключить подобие модели, но по умолчанию она не включена в сборку и существует скорее для тех, кто ещё не до конца освоил возможности JavaScript.
Пара простых примеров под конец
Как в Vue использовать свои компоненты
Предельно интуитивно:
<some-component-name prop1="hello" prop2="23">
<span>Content inside also available</span>
</some-component-name>
Как узнать список абсолютно всех свойств компонента
Хороший код сам себя документирует, и здесь именно такой случай. Свойство props в определении компонента:
props: ['name', 'label', 'checked']
или
props: {
page: Number,
count: Number,
hideInitTestLink: {type: Boolean, default: false}
}
Как повесить обработчики событий
<input :value="someValue" @blur="someParentComponentMethod" />
<button @click="someParentComponentMethod">submit</button>
<button @click.prevent="someParentComponentMethod">make something</button>
комментарии (397)