В данной статье речь пойдет о замечательном фронтенд фреймворке Vue.js. Как вы видите, статья называется «Vue.js для сомневающихся», и, если вы до сих пор не могли решиться попробовать Vue.js на практике, то надеюсь, что после прочтения вы все-таки на это решитесь.
Фреймворки разрабатываются для того, чтобы упростить нам жизнь и освободить от написания однотипного кода. Но, по мере того как кодовая база некоторых фреймворков сильно разрастается, они начинают привносить свою долю сложности в проект. Из-за этого при планировании разработки мы должны учитывать два фактора:
- сложность нашего приложения
- сложность фреймворка, который мы используем
Немного абстрагируемся и назовём это внутренней сложностью (то есть сложностью, от которой мы не можем избавиться при разработке) и сложностью инструмента, с помощью которого мы достигаем той или иной цели. Естественно манипулировать мы можем только сложностью инструмента.
Из вышесказанного, у нас получается два варианта выбора инструмента:
- Вариант недостаточности. Когда инструмента недостаточно, чтобы перекрыть внутреннюю сложность. Функции, необходимые для реализации приложения, отсутствуют в фреймворке, и нам приходится вручную дорабатывать и добавлять необходимый инструментарий.
- Вариант избыточности. Когда необходимый для приложения функционал перекрывается только небольшой частью инструмента. Остальная же часть инструментария висит мертвым грузом и только создает нам проблемы: ограничения при разработке, замедление загрузки приложения и т.п.
Так что же делать? Возможно, буду немного Капитаном Очевидностью, но надо действовать по принципу: “Для каждой цели — свой инструмент”. При планировании нам необходимо искать золотую середину так, чтобы сложность (и, следовательно, функциональность) приложения были на одном уровне.
О Vue.js и авторе
Итак, разберемся с Vue и каким образом он может облегчить нам разработку приложения.
Создателем Vue.js является Evan You, бывший сотрудник Google и Meteor Dev Group. Начал он разрабатывать фреймворк в 2013-м, а в феврале 2014-го состоялся первый публичный релиз. Vue широко используется среди китайских компаний, например: Alibaba, Baidu, Xiaomi, Sina Weibo и др. Он входит в ядро Laravel и PageKit. Недавно свободная система управления репозиториями GitLab тоже перешла на Vue.js.
В конце сентября 2016-го вышел в релиз Vue.js 2.0, еще круче и с упором на производительность — теперь используется виртуальный DOM, поддерживается серверный рендеринг, возможность использовать JSX и т.д. Хотя сейчас он поддерживается только сообществом, он держится достойно даже на уровне продуктов таких гигантов, как Google и Facebook (Angular2 и React 15), и постепенно догоняет их по популярности.
Рассмотрим самый простой пример:
app.js
var demo = new Vue({
el: '#demo',
data: {
message: 'Hello, Singree!'
}
})
- создается новый инстанс вью через new Vue
- в el мы определяем, за каким элементом следит вью
- в data у нас объект состояния
app.html
<div id="demo">
<p>{{message ? message : "no content"}}</p>
<input v-model="message">
</div>
- в html, естественно, у нас должен быть элемент с нужным нам селектором
- данные из состояния выводим в усатом (mustache ведь) синтаксисе. Тут у нас обычное тернарное выражение
- инпут связываем со значением message объекта состояния с помощью директивы v-model
//codepen.io/Demetrius/embed/KNaJLW/?height=468&theme-id=16150&default-tab=result
Концепции Vue.js
Основными концепциями Vue являются:
- конструктор
- компоненты
- директивы
- переходы
В первой версии еще были фильтры, но, насколько я знаю, в текущей версии они считаются deprecated.
Конструктор
app.js
new Vue({
el: '<jQueryStyleSelector>',
template: '<id || inline template>',
data: {
props: 'Это видно в шаблонах',
first_name: "Вася",
last_name: "Пупкин"
},
computed: {
full_name: function(){
return this.first_name + this.last_name; //Вася Пупкин
}
},
methods: {
// методы жизненного цикла
beforeCreate: function(){},
created: function(){},
beforeMount: function(){},
mounted: function(){},
beforeUpdate: function(){},
updated: function(){},
beforeDestroy: function(){},
destroyed: function(){},
customMethodsAlso: function(){
//здесь у нас тоже есть доступ к data
}
}
})
Работа с Vue.js начинается с создания нового инстанса new Vue. В el у нас элемент, за которым следит Vue. В template выбран (либо прописан инлайново) элемент, куда Vue будет рендерить. В data хранится текущее состояние инстанса, а метод computed предоставляет нам вычисляемые свойства.
В примере вычисляемое свойство full_name отслеживает first_name и last_name как зависимости и автоматически синхронизируется.
В methods можно выделить следующие кастомные методы и методы жизненного цикла Vue:
- beforeCreate — смотрит данные и инициализирует события
- created — смотрит, есть ли el или template. Если есть, то рендерит в них; если нет, то ищет метод render
- beforeMount — создает vm.$el и заменяет им el
- mounted — элемент отрендерен
При изменении состояния:
- beforeUpdate — снова рендерит VDOM и сравнивает с реальным DOM-ом, применяет изменения
- updated — изменения отрендерены
- beforeDestroy — полный демонтаж вотчеров, внутренних компонентов и слушателей событий
- destroyed — вызывается, когда выполнение операции останавливается
Директивы
Директивы — специальные атрибуты для добавления элементам html дополнительной функциональности.
Рассмотрим некоторые встроенные директивы (кто работал с Angular, тому они покажутся очень знакомыми):
- V-bind — динамически связывается с одним или несколькими атрибутами.
- V-cloak — прячет “усатые” выражения, пока не подтянулись данные
- v-if — условие для рендера элемента
- V-else — обозначает “else блок” для v-if
- V-for — циклично проходит массив объектов
- V-model — связывает состояние с input элементом
- V-on — связывает слушателя события с элементом
- V-once — рендерит элемент только вначале и больше не следит за ним
- V-pre — не компилирует элемент и его дочерние элементы
- V-show — переключает видимость элемента, изменяя свойство CSS display
- V-text — обновляет textContent элемента
Все Vue-директивы имеют префикс “v-”. В директиву передается какое-то значение состояния, а в качестве аргументов могут быть атрибуты html или события.
html
<div v-my-directive="someValue"></div>
js
Vue.directive('my-directive', {
bind: function () {
// подготовительные работы
// добавление слушателей событий и других ресурсоемких функций,
// которые должны быть запущены только один раз
},
update: function (newValue, oldValue) {
// делаем что-то с обновленным значением
},
unbind: function () {
// производим очистку
// удаляем слушателей событий, добавленных в bind()
}
})
Компоненты
Компоненты помогают расширить основные html элементы и внедрить переиспользуемый код. По сути, компоненты — повторно используемые части UI. На этапе проектирования мы разбиваем наше приложение на независимые части и получаем древовидную структуру компонентов.
В Vue.js нет особых требований к именам компонентов, но хорошая практика — придерживаться правил W3C насчет кастомных компонентов, то есть буквы нижнего регистра и разделения через дефис.
app.js
Vue.component('simple-counter', {
template: '<button v-on:click="counter += 1">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
}
})
new Vue({
el: '#demo'
})
Новый компонент объявляется с помощью Vue.component, и в первый аргумент мы передаем имя нового тега (в нашем случае simple-counter)
//codepen.io/Demetrius/embed/ObgyQP/?height=468&theme-id=16150&default-tab=result
Коммуникация между vue-компонентами осуществляется по принципу “Props in, Events out”. То есть от родительского элемента к дочернему информация передается через пропсы, а обратно — вызываются события.
Также во Vue.js есть так называемые однофайловые компоненты. Мы создаем файл с расширением .vue и пишем туда стили, шаблон и логику. Причем писать можно на любом удобном вам препроцессоре (SASS, Stylus, PostCSS, Jade, ...) и языке, компилирующимся в JS (CoffeeScript, TypeScript).
app.js
// comment.vue
<style lang="sass">
button {
border: 1px solid gray;
&.blue { border-color: blue; }
}
</style>
<template lang="jade">
avatar(:user='user')
input(type='text', v-model='content')
button.blue(@click='submitComment')
</template>
<script>
import Comment from '../models'
import avatar from './components/avatar.vue'
export default {
props: ['user'],
components: {
avatar
},
data () {
return {
content: ''
}
},
methods: {
submitComment (e) {
e.preventDefault();
var comment = new Comment(this.content)
comment.save().then(() => {
alert('o_O')
this.content = ''
})
}
}
}
</script>
Переходы
Vue предоставляет различные способы применения анимационных эффектов, когда элементы отрисованы, обновлены или удалены из DOM. Они включают в себя инструменты для:
- автоматического применения классов для CSS-переходов и анимаций
- интеграции сторонних библиотек для CSS-анимаций, таких как Animate.css
- использования JavaScript для манипуляции DOM-ом
- интеграции сторонних JavaScript библиотек для анимаций, таких как Velocity.js
Рассмотрим простой пример:
html
<div id="demo">
<button @click="show = !show">Toggle show</button>
<transition name="bounce">
<p v-if="show">Look at me!</p>
</transition>
</div>
js
new Vue({
el: '#demo',
data: {
show: true
}
})
//codepen.io/Demetrius/embed/ZByQzx/?height=490&theme-id=16150&default-tab=result
Экосистема фреймворка
Роутинг
Во Vue.js за маршрутизацию отвечает отдельный пакет vue-router. Он поддерживает вложенные маршруты к вложенным компонентам, предлагает упрощенное API для навигационных хуков, управляемое поведение скрола и продвинутый контроль переходов.
Вот небольшой пример:
app.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './app.vue'
import ViewA from './view-a.vue'
import ViewB from './view-b.vue'
Vue.use(VueRouter)
const router = new VueRouter()
router.map({
'/a': { component: ViewA },
'/b': { component: ViewB }
})
router.start(App, '#app')
app.vue
<div>
<h1>Это шаблон, который не будет меняться</h1>
<router-view><!-- выбранные компоненты рендерятся здесь --></router-view>
</div>
Ajax-запросы
Для работы с Ajax-запросами существует плагин vue-resource. Он предоставляет возможности для создания веб-запросов и обработки ответов с помощью XMLHttpRequest или JSONP. Также особенностью плагина является поддержка Promise API и URI шаблонов.
Пример:
js
{
// GET /someUrl
this.$http.get('/someUrl').then((response) => {
// успех
}, (response) => {
// или ошибка
});
}
Управление состоянием
Vuex — паттерн и библиотека управления состоянием для приложений на Vue.js. Он предоставляет централизованное общее состояние для всех компонентов в приложении и правила, обеспечивающие предсказуемое изменение состояния.
На изображении ниже представлено приложение на Vue+Vuex со следующими частями:
- Состояние (State), которое является единственным источником данных для компонентов.
- Vue-компоненты(Vue-components), которые по сути являются лишь декларативным отображением состояния.
- Действия (Actions), которые отлавливают событие, которое произошло, собирают данные с внешних API и запускают нужные мутации.
- Мутации (Mutations) — единственная часть, которая может изменять состояние и, получив данные от Actions, применяет их на состоянии.
Система сборки и инструменты разработчика
Для отладки в браузере существует Vue-devtools (к сожалению, пока только для Chrome), который позволяет видеть, какие компоненты есть в нашем приложении и их текущее состояние.
Также он прекрасно работает с Vuex и позволяет выполнять так называемый time-travel debugging: в браузере мы можем увидеть историю состояний и переключаться между ними.
Почему я должен его использовать
Vue удивителен! Я считаю, это здорово, что я могу просто подключить его на странице и начать работать без необходимости шаманить с системой сборки или CLI. С ним очень просто начать работать, даже если вы никогда не работали с JavaScript фреймворками. Это идеальное сочетание удобства и мощности. Рассмотрим еще несколько аргументов в его пользу:
- Теперь он еще меньше. Runtime сборка Vue.js 2.0 весит всего лишь 16kb, а вместе с vue-router и vuex — 26kb (примерно как и ядро первой версии).
- Он еще быстрее. Во Vue.js всегда уделялось большое внимание быстродействию. Прослойка, отвечающая за рендеринг, переписана на облегченную реализацию виртуального DOM-а — форка Snabbdom.
- Vue 2.0 поддерживает серверный рендеринг. Для этого есть модуль Vue-server-renderer, поддерживающий другие инструменты из экосистемы Vue (vue-router и vuex). Теперь гораздо проще создавать изоморфные приложения.
- Ребята из Alibaba работают над Weex, кроссплатформенным нативным мобильным UI (как ReactNative и NativeScript). Отныне Vue-компоненты можно будет использовать для веб, Android и iOS.
Vue прошёл путь от небольшого аматорского проекта до широко используемого проекта с большим сообществом, а я надеюсь, что сумел развеять ваши сомнения по поводу того, стоит использовать этот фреймворк или нет.
Спасибо за внимание!
Статью подготовили: greebn9k (Сергей Грибняк), Dmitry-Ivanov (Дмитрий Иванов), silmarilion (Андрей Хахарев)
Комментарии (44)
x07
25.05.2017 13:26… без необходимости шаманить с системой сборки
В любом приложении, которое состоит не из 5 кнопок и 2 инпутов, без систем сборки/таскраннеров не обойтись.tenbits
25.05.2017 15:03Верно, но это только для релиза. А вот при разработке сборки и таскраннеры только мешают.
Yeah
25.05.2017 15:44+1Это так, но зато Vue можно постепенно внедрять в legacy-код, просто подключив на странице и создав экземпляр Vue
i360u
25.05.2017 13:42Перед тем, как пробовать замечательный (не сарказм) Vue, попробуйте Polymer. Пора уже использовать возможности веб-платформы вместо мета-платформ и костылей. Ну и это даст отличный шанс по новому взглянуть на такие вещи как "серверный рендеринг", бандлинг, роутинг и т. д. и т. п.
gubber
26.05.2017 11:19Пробовал 9 месяцев назад полимер.
На FF более менее среднее приложение тормозит безбожно — открывалось до 10 секунд.
В хроме проблем не былоi360u
26.05.2017 15:26С тех пор уже вышла новая версия спецификаций веб-компонентов (v1), и Polymer 2.0. Очень советую посмотреть на ютубе секции про компоненты и Полимер с последнего Google I/O.
fijj
25.05.2017 14:22+1Сам стоял перед выборов vue или react. Vue подкупил легкостью в изучение, более читаемые шаблоны на фоне jsx, хотя при большой вложенности компонентов читать сложно. Но вот ни как не могу понять, какую лучше структуру проекта применять при использование vuex. Обычно все стремятся распихать мутации в один файл, экшены в другие, а если еще и на модули разбито, становится сложно ориентироваться по папкам и в куче открытых вкладок ide.
Dmitry-Ivanov
25.05.2017 14:46Обычно в одну папку собираю компонент (или несколько компонентов), отвечающий за определенную фичу и туда же кидаю файл vuex-модуля для этой фичи. А эти модули уже подключаю в рутовый файл vuex.
DenimTornado
25.05.2017 16:14А почему Ember не рассматривали? Бегло по статье пробежался, очень похоже…
Dmitry-Ivanov
26.05.2017 13:32+1Как по мне, у Ember гораздо более высокий порог вхождения и необходимость четко следовать определенным правилам. У Vue же больше свободы, но как минус — архитектуру приходится полностью продумывать самому.
Diaskhan
25.05.2017 14:39+3Очень удобная библиотека для использования бустрапа вместе с vue js
https://github.com/bootstrap-vue/bootstrap-vue
Я вкурил Vue, после него сомневаюсь что будет, что-то лучше!
Кривая обучения у vue проще паренный репы.Quilin
26.05.2017 13:43-1ПроститеXAHTEP26
25.05.2017 15:01Отличная статья. Я уже начинал погружение во Vue и мне он очень понравился. Но из-за недостатка свободного времени пришлось пока отложить его. Поэтому читать статью и снова вспоминать как это красиво реализовано было приятно.
Хотелось бы еще более подробное описание про Vuex, так как без него врядли можно сделать серьезное приложение.
Daemos
25.05.2017 15:12Мы используем Vue 1.0 в X-Cart 5 и впечатление от использования отличное, годные доки и прочее.
Самостоятельно реализовали возможность перерендерить компонент темплейтом и значениями из любого промиса, в т.ч. ajax-запроса. К сожалению, авторы во второй версии решили выпилить form input как источник изначальных значений и это нам сильно обламывает переход на нее.
Самое крутое в этой либе — то, что она очень хорошо ложится на существующий html-код, есть привязки к нативным эвентам, атрибутам элементов и прочее. Vue гораздо легче встроить в существующий проект (по сравнению с React, Angular 2 напр.)
PaulMaly
27.05.2017 13:24Использую Ractive, с которого Vue и «слизывали». Там из коробки есть такая штука как адапторы (adaptors), с их помощью можно легко зареактивить объект любого типа. Поэтому я делаю так:
ractive.set('products', api.get('products'));
И никаких запар. А относительно недавно стал вместо «голых» промисов работать с Rx, там с управлением потока данных поинтереснее вещи можно делать и также автоматом реактивить в Ractive инстансы.vintage
28.05.2017 19:47-1Вот вы-то мне и нужны. Можете подсказать, как на Rx сделать достаточно простую вещь с потоком данных? https://toster.ru/q/427478
xxxTy3uKxxx
25.05.2017 16:17+1Спасибо за статью. Стоит отметить, что авторы vue-resource как-то писали, что теперь эта библиотека более не является частью "официальной рекомендации" Vue и советовали смотреть в сторону других библиотек (например, Axios)
unsafePtr
25.05.2017 16:57+1Меня вот смущают .vue однойфайловые компоненты. Это ведь нужна поддержка от ide для удобной разработки. Как ide определит, на чем вы пишете логику, на typescript-e или javascript-e, или мы используем sass, post-css. Кто сталкивался, подскажите. А желательно с примером кода на гитхаб. Спасибо.
xxxTy3uKxxx
25.05.2017 17:46Указываете
lang
вstyle
и всех дел.
Документация
These specific languages are just examples. You could just as easily use Buble, TypeScript, SCSS, PostCSS — or whatever other preprocessors that help you be productive. If using Webpack with vue-loader, it also has first-class support for CSS Modules.
UZERE
25.05.2017 18:30lang можно указать для всех трёх элементов vue-файла. Если поставить шаблон webpack через vue-cli, то нужно только доставить соответствующие пакеты и всё будет работать (документация по шаблону). Сам использовал pug(jage) и stylus.
Например, для Sublime Text есть Vue Syntax Highlight, который нормально подсвечивает vue-файлы и подхватывает нужную подсветку из lang.
serf
26.05.2017 10:10Ничего не мешает .vue файл использовать просто для группировки, а сами файлы (шаблон, код, стили) внутри подключючить как внешние файлы.
EduardNikolenko
26.05.2017 16:37Если нет поддержки в IDE, можете для всех элементов указать src и разнести по отдельным файлам:
<template lang="jade" src="./template.jade"></template> <script src="./script.ts"></script> <style lang="sass" src="./style.sass"></style>
AmdY
26.05.2017 00:07Интересует будущее Vue, где можно почитать о планах? За последние годы я переел этих тайпскриптов, флоу, вебпаков и *-cli. Сейчас в отпуске свой пет проект начал писать на первом angular, без всяких обвесок и вдруг вспомнил, что люблю программирование.
Vue выглядит как неплохая альтернатива angular1, да и схожесть упрощает освоение, но она же пугает, как бы авторы не пошли по тому же пути c предпроцессорами, типизацией и функциональщиной.
GriNAME
26.05.2017 01:42Спасибо за статью! Очередной раз убеждаюсь что я сделал правильный выбор) и смотрю в комментариях большинство очень положительно относиться к Vue.
Сам выбирал между вью и ангуляр, и вью показался таким простым и каким-то уютными)
Есть те кто уже довольно опытные люди в последних версиях вью и ангуляр чтобы дать своё сравнение? У меня к сожалению не очень большой опыт работы с обоими фреймворками.
serf
26.05.2017 10:12и каким-то уютными)
Потому что это так и есть, это очень developers friendly штука, забыл например описать поле в data — фреймворк тебе подскажет не тупи мол.
vintage
28.05.2017 19:51Если бы он это ещё на этапе написания кода подсказывал или на этапе компиляции, а не в рантайме и то, когда исполнение дойдёт до нужного участка кода, если дойдёт.
x07
26.05.2017 10:13Не надо пытаться найти идеальный инструмент. Каждый решает определенные задачи, а Angular 4 и vue.js вещи не сравнимые.
PaulMaly
26.05.2017 12:43Статья хорошая, спасибо! По поводу Vue, написал на нем 2 проекта и честно говоря ожидал большего. По существу это своеобразный подражатель Ractive, с определенными и, лично на мой взгляд, не совсем удачными заимствованиями из других фреймверков.
Конечно, на фоне остальных хайповых фреймверков, типа Angular и React, Vue выглядит наиболее удобоваримым. Однако, многие его решения показались мне не слишком удобными и продуманными. Поэтому снова вернулся к работе с Ractive, который, лично для меня, гараздо удобнее и продуманнее.
Справедливости ради, нужно отметить, что у Vue есть и неоспаримые плюсы по сравнению с Ractive:
- Vue быстрее по бренчмаркам, чем Ractive. Во всяком случае 2-я версия.
- Ractive не слишком хайповый, развивается спокойно и стабильно (что скорее плюс), но готовых решений и т.п. намного меньше и само комьюнити тоже.
- Из-за того что Ractive менее хайповый (у Vue в 10 раз больше звезд на GitHub) найти вакансию с ним сложнее.
В любом случае, как девелопер я скорее маргинал, поэтому мои предпочтения обычно не слишком соответствуют всеобщему тренду. Поэтому прошу сильно не минусовать и помнить, что любое мнение может быть высказано.
Alex_2222
26.05.2017 16:36Для отладки в браузере существует Vue-devtools (к сожалению, пока только для Chrome)
Не совсем верно
Heavis
26.05.2017 16:36Ещё у Vue восхитительная документация, полностью на русском. Для меня как новичка это снизило порог входа, который и без того низкий.
А для нативных приложений вроде есть официальный Vux, но там пока доки только китайские.
DDroll
26.05.2017 16:36Пришлось для отдельного проекта поизучать Vue, очень пока нравится. У меня, как у angularjs разработчика с 3-х летним стажем, сложилось впечатление, что Vue — это Angular 2 такой, каким он должен был быть и каким его все ждали. Из серьезных минусов — отсутствие хайпа (а это равно отсутствию мануалов, большого количества готовых модулей и альтернатив им) и нежелание авторов хайпить; уклон документации и комментов в китайский. Заиметь бы Вью крупную западную компанию в покровителях, думаю, с легкостью догнал бы «титанов» по популярности.
PaulMaly
26.05.2017 23:35Это у Vue то нет хайпа? Да он один из трёх самых трендовых фреймверков на данный момент и уж точно стоит в одном ряду с React и Angular. Список спонсоров у него весьма не маленький, хоть там и нет титанов индустрии. Да и всевозможных либ для Vue уже не мало понаписали.
Alex_2222
26.05.2017 17:07Для отладки в браузере существует Vue-devtools (к сожалению, пока только для Chrome)
Не совсем верно
https://github.com/vuejs/vue-devtools/blob/master/docs/workaround-for-firefox.md
Hazrat
За Vue.js никто не стоит? А разве Alibaba не является фактически владельцем? я не против, я за то чтобы большие компании поддерживали хороший продукт.
Еще интересно сравнение, с ReactJS, чем обоснован график, где пример кода, используется ли оптимизация в ReactJS (PureComponent к примеру)?
Dmitry-Ivanov
Да, где-то сталкивался с информацией, что больше половины финансирования идет от Алибабы.
Графики основываются на вот этом сравнении js-фрейморков.
ZoomLS
У React ещё лицензия менее свободная, чем у Vue.