Upload
ontico
View
597
Download
3
Embed Size (px)
Citation preview
Vue.js и его брат-близнец VueServer.jsАндрей Солодовников
1.4
Vue [Вю] (франц.) — Вид
Vue [Вю] (франц.) — Вид
Vue → View [Вью]
5 летFrontend/JavaScript developer
7 летВелосипедист
Недвижимость
Вся Россия
Недвижимость
Вся Россия
2 года в разработке
НГС.НЕДВИЖИМОСТЬ
realty.ngs.ru
НГС.НЕДВИЖИМОСТЬ
realty.ngs.ru
Сложный Frontend:что выбрать?
WEB COMPONENTS
React (v15.1.0)Vue.js (v1.0.24)
React (v15.1.0)
43k
Vue.js (v1.0.24)
20kЗвездочек на GitHub
React (v15.1.0)
43k
IE9+
147 (43) kb
Vue.js (v1.0.24)
20k
IE9+
76 (26) kb
Звездочек на GitHub
Поддержка
Размер
React (v15.1.0)
43k
IE9+
147 (43) kb
550ms
Vue.js (v1.0.24)
20k
IE9+
76 (26) kb
450ms
Звездочек на GitHub
Поддержка
Размер
Стартует за*
* В моём личном тесте
Application
List
Item x250
Evan You
Data
Data + watchers
Data + watchers DOM
Data
Data + watchers DOM
Data + watchers
ReactiveBindings
Директивы
v-if
v-for
v-show
v-text
v-html
v-bind
v-on
v-if
v-for
v-show
v-text
v-html
v-bind
v-on
ng-if
ng-repeat
ng-show
ng-bind
ng-bind-html
ng-style, ng-class...
ng-click, ng-change...
<div v-if="false">Не отрисуется</div><div v-else>Отрисуется</div>
<div v-if="false">Не отрисуется</div><div v-else>Отрисуется</div>
<div>Отрисуется</div>
<div v-bind:class=" 'foo' "></div>
<div v-bind:class=" 'foo' "></div><div :class=" 'foo' "></div>
<div v-bind:class=" 'foo' "></div><div :class=" 'foo' "></div><div :class=" ['foo', {bar: true}] "></div>
<div class="foo"></div><div class="foo"></div><div class="foo bar"></div>
Усатые выражения
<div>{{ someText }}</div>
<div>{{ someText }}</div><div>{{* someText }}</div>
<div>{{ someText }}</div><div>{{* someText }}</div><div>{{{ someHtml }}}</div>
<div>{{ someText }}</div><div>{{* someText }}</div><div>{{{ someHtml }}}</div>
<div title="Было {{pubDate}}">
<div>{{ someText }}</div><div>{{* someText }}</div><div>{{{ someHtml }}}</div>
<div title="Было {{pubDate}}"><div title="Было {{pubDate | dateFull}}">
Lifecycle + Hooks
Data Scope
Template + Children
Destroy
Attach
created
compiled
ready
destroyed
Data Scope
Template + Children
Destroy
Attach
created
compiled
ready
destroyedbeforeDestroy
beforeCompiled
Data Scope
Template + Children
Destroy
Attach
created
compiled
ready
destroyedbeforeDestroy
beforeCompiled
activate
Создание компонентов
export default { // ...}
Создание компонентов
template: '<h1>Hello world</h1>',
template: '<h1>Hello world</h1>',data () { return { cats: 1, dogs: 2 };}
template: '<h1>Hello world</h1>',data () { return { cats: 1, dogs: 2 };},methods: { … }
template: '<h1>Hello world</h1>',data () { return { cats: 1, dogs: 2 };},methods: { … },computed: { summ () { return this.cats + this.dogs; } // 3}
created () { … }beforeCompiled () { … }compiled () { … }activate () { … }ready () { … }beforeDestroy () { … }destroyed () { … }
Vue.component('MyBlock', { … });
Vue.component('MyBlock', { … });
export default { // ... components: { MyBlock: { … } }}
<my-block></my-block>
<my-block></my-block><component is="MyBlock"></component>
<my-block></my-block><component is="MyBlock"></component><tbody is="MyBlock" v-for="block in blocks"></tbody>
const Root = { el: 'body', template: '<div>...</div>'};
new Vue(Root);
Динамические компоненты
template: '<component :is=" name + 'Page' "></component>',data: { name: 'Main'}
template: '<component :is=" name + 'Page' "></component>',data: { name: 'Main'},components: { MainPage: {...}, ArticlesPage: {...}}
Главная
template: '<component :is=" name + 'Page' "></component>',data: { name: 'Articles'},components: { MainPage: {...}, ArticlesPage: {...}}
Статьи
Обработка событий
<button v-on:click="onButtonClick($event)"></button> <button v-on:click="isVisible = !isVisible"></button>
Обработка событий
<button v-on:click="onButtonClick($event)"></button> <button v-on:click="isVisible = !isVisible"></button> <button @click="isVisible = !isVisible"></button>
Обработка событий
<button @click="isVisible = !isVisible"> {{ isVisible ? 'Скрыть' : 'Показать' }}</button><div v-show="isVisible">Содержимое</div>
Показать
Содержимое
Скрыть
Данные между компонентами
{ message: 'Привет!' }<child></child>parent
child{ }<div></div>
{ message: 'Привет!' }<child></child>parent
child{ }<div></div>
Как передать?
{ message: 'Привет!' }<child></child>parent
child props: { ... }{ }<div></div>
Как передать?
props: { value: null}
props: { value: { required: true, default: 'foo', type: String, validate () {…} }}
{ message: 'Привет!' }<child></child>parent
child props: { value: null }{ }<div></div>
{ message: 'Привет!' }<child :value="message"></child>parent
child props: { value: null }{ }<div></div>
{ message: 'Привет!' }<child :value="message"></child>parent
child props: { value: null }{ value: 'Привет!' }<div>Привет!</div>
<child :value="message"></child><child :value.once="message"></child><child :value.sync="message"></child>
parent (*)→ childparent (1)→ childparent ←→ child
● vue-router, vuex…
● Slot API
● DevTools (Hot Reload + TimeTravel)
● Шикарные доки
А ещё...
Попробуйте Vue.js 1 день(серьёзно)
Что делать с SEO?
Что делать с SEO?
Хочу видеть контент сразу!
Умеет?
Время
250ms
210ms
430ms
Версия
15.0.2
0.14.8
0.13.3
* В моём личном тесте, NODE_ENV=production
React: SSR
Другие решения
Другие решения
● Эмуляция (jsdom, PhantomJS)
Другие решения
● Эмуляция (jsdom, PhantomJS)
● Snapshots / Prerender.io
Другие решения
● Эмуляция (jsdom, PhantomJS)
● Snapshots / Prerender.io [SEO]
VueServer.js
Почему это не сложно?
Почему это не сложно?
● Vue.js — простой
Почему это не сложно?
● Vue.js — простой● Реактивность — не нужна
Почему это не сложно?
● Vue.js — простой● Реактивность — не нужна● Кроссбраузерность — забудьте
Почему это не сложно?
● Vue.js — простой● Реактивность — не нужна● Кроссбраузерность — забудьте● Не всё писать с нуля
Рендерим.Как поступить с данными?
Request → State
Request → State
getData()
Request → State
getData()
App
Content
Request → App
Content
Request → App
Content
COMPILED
Request → App
Content
getData()
Request → App
Content
import {renderer} from 'vue-server';const Vue = new renderer();
new Vue({ template: '<div>Hello world!</div>'})
import {renderer} from 'vue-server';const Vue = new renderer();
new Vue({ template: '<div>Hello world!</div>'}) .$on('vueServer.htmlReady', (html) => { res.send(html); // '<div>Hello world!</div>' });
import {compiler} from 'vue-server';
export default { template: compiler('<div>.../div>')}
Пре-компиляция шаблонов
npm install gulp-vue-compile
Пре-компиляция шаблонов
Время
430ms
250ms
* В моём личном тесте
React vs VueServer
Время
430ms
250ms
150ms
* В моём личном тесте
React vs VueServer
Время
30ms
50ms
100ms
Объявление
Главная
Поиск
Рендеринг страниц N1.RU
Серверный → Клиентский HTML
Подходы
● Подхват (сохранение разметки)
● Замена (re-rendering)
Пере-рендериваем
Server HTML
head
body
head
body{{ body }}
head
{{ body }}
body
head
body
body
head
body
body
head
body
body
head
body
body
import {renderer} from 'vue-server';const Vue = new renderer();
Vue.prototype.$isServer = true;
<span v-if="$isServer">Загрузка...</span><select v-else> ...</select>
VueServer: недостатки
VueServer: недостатки
● Версия 1.0.0-migration
VueServer: недостатки
● Версия 1.0.0-migration
● Свои директивы — нельзя
VueServer: недостатки
● Версия 1.0.0-migration
● Свои директивы — нельзя
● vue-router и другое — не поддерживается
Vue 2.0
Vue 2.0
● SSR «из коробки»
Vue 2.0
● SSR «из коробки»
● API ещё проще (на ~90% совместимо с 1.x)
Vue 2.0
● SSR «из коробки»
● API ещё проще (на ~90% совместимо с 1.x)
● render ()
Спасибо за внимание!
http://n1.ru/http://vuejs.org/guide/https://www.npmjs.com/package/vue-server/https://www.npmjs.com/package/gulp-vue-compile/
Андрей СолодовниковJS-разработчик «НГС Технологии»[email protected]