knockout.js на примере 2ГИС-Онлайн
DESCRIPTION
TRANSCRIPT
САЛЬНИКОВ СТАНИСЛАВ
KNOCKOUT.js НА ПРИМЕРЕ 2ГИС-ОНЛАЙН
WWW.2GIS.RU
Пользователь
2ГИС Онлайн
API Справочника
АРХИТЕКТУРА WEB-APP
АРХИТЕКТУРА CLIENT-SIDE APP
Пользователь
2ГИС Онлайн
API Транспорта
API пробок
API <Место для
вашего сервиса>
API Справочник
API Карт +1
WWW.2GIS.RU
DOM НА КЛИЕНТЕ
WWW.2GIS.RU
DOM НА КЛИЕНТЕ
var newDiv = document.createElement('div'); newDiv.className = 'my-class'; newDiv.id = 'my-id'; newDiv.innerHTML = 'Привет, мир!';
document.body.appendChild(newDiv);
Привет, мир!
WWW.2GIS.RU
WHERE IS
ШАБЛОНИЗАТОРЫ
jQueryTemplate
Mustache
Underscore.js
Шаблонизатор резига
Pure
WWW.2GIS.RUWWW.2GIS.RU
СОБЫТИЯ
.firmShort .firmFull
WWW.2GIS.RUWWW.2GIS.RU
#firmList
СОБЫТИЯ
$("#firmTemplate").tmpl(someData).appendTo("#firmList");
$('.firmShort').live({ click: function() { showFirmCard(this); } });
$('.firmFull').live({ click: function() { hideFirmCard(this); } });WWW.2GIS.RUWWW.2GIS.RU
WWW.2GIS.RUWWW.2GIS.RU
СОБЫТИЯ
KNOCKOUT
WWW.2GIS.RUWWW.2GIS.RU
ПОЧЕМУ KNOCKOUT?
Активно развивается
WWW.2GIS.RUWWW.2GIS.RU
● Активно развивается
ПОЧЕМУ KNOCKOUT?
Удобное разделение логики и шаблонов
WWW.2GIS.RUWWW.2GIS.RU
● Активно развивается● Удобное разделение логики и шаблонов
ПОЧЕМУ KNOCKOUT?
Функционален, есть декларативные биндинги
WWW.2GIS.RUWWW.2GIS.RU
● Активно развивается● Удобное разделение логики и шаблонов● Функционален, есть декларативные
биндинги
ПОЧЕМУ KNOCKOUT?
Низкий порог вхождения
WWW.2GIS.RUWWW.2GIS.RU
MVVM
View Model
ViewModel
UI Logic Business Logic
Application Logic
WWW.2GIS.RUWWW.2GIS.RU
MVVM
ViewModel
WWW.2GIS.RUWWW.2GIS.RU
Данные
Вспомогательные функции
Связывание данных с отображениемKO
KNOCKOUT
WWW.2GIS.RUWWW.2GIS.RU
<div> <span data-bind="text: what"></span>, <span data-bind="text: where"></span></div>
KNOCKOUT
WWW.2GIS.RUWWW.2GIS.RU
function vm() {this.what = ko.observable('');
}
KO.OBSERVABLE
WWW.2GIS.RUWWW.2GIS.RU
function vm() {this.what = ko.observable('');
}ko.applyBindings(new vm());
KO.OBSERVABLE
WWW.2GIS.RUWWW.2GIS.RU
function vm() {this.what = ko.observable('');
}ko.applyBindings(new vm());
vm.what(response.what);
<span data-bind="text: what"></span>
KO.OBSERVABLE
WWW.2GIS.RUWWW.2GIS.RU
МАССИВЫ
WWW.2GIS.RUWWW.2GIS.RU
response.result = [ { firmName = 'Завод №1', ... }, { firmName = 'Завод №2'; ... }]
МАССИВЫ
WWW.2GIS.RUWWW.2GIS.RU
function vm () {this.firms = ko.observableArray([]);
}...vm.firms(response.result);
<div data-bind="foreach: firms"><div data-bind="text: firmName"></div>
</div>
KO.OBSERVABLE_ARRAY
WWW.2GIS.RUWWW.2GIS.RU
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
<div> <span data-bind="text: what"></span>, <span data-bind="text: where"></span></div>
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
BINDINGS
- Текст и стиль блока
- Control flow
- Работа с формами
- Шаблонизация
- События
WWW.2GIS.RUWWW.2GIS.RU
- <место для ваших идей>
BINDINGS
.firmShort .firmFull
WWW.2GIS.RUWWW.2GIS.RU
#firmList
<div id="firmList" data-bind="foreach: firms"><div class="firmShort"
data-bind="visible: !isVisible"></div><div class="firmFull"
data-bind="visible: isVisible"></div></div>
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
data-bind="visible: isVisible,click: toggleVisibility"
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
data-bind="visible: isVisible,click: toggleVisibility"
toggleVisibility = function() { this.isVisible(!this.isVisible());}
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
ko.bindingHandlers['visible'] = { 'update': function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); var isCurrentlyVisible = !(element.style.display == "none"); if (value && !isCurrentlyVisible) element.style.display = ""; else if ((!value) && isCurrentlyVisible) element.style.display = "none"; }};
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
ko.bindingHandlers['animateVisible'] = { 'update': function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); var isCurrentlyVisible = !(element.style.display == "none"); var slideSpeed = 200; if (value && !isCurrentlyVisible) $(element).slideDown(slideSpeed, callback); else if ((!value) && isCurrentlyVisible) $(element).slideUp(slideSpeed, callback); }};
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
data-bind="animateVisible: isVisible,click: toggleVisibility"
toggleVisibility = function() { this.isVisible(!this.isVisible());}
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
<script type="text/my-tpl" id="firm-tpl"> // Put yor awesome template here!</script>
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
<script type="text/my-tpl" id="catalog-tpl"> <div data-bind="template: { name: 'firm-tpl', foreach: firms }"></div>
</script>
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
BINDING-CONTEXT
vm
vm.firms[n]
WWW.2GIS.RUWWW.2GIS.RU
context === $data
BINDING-CONTEXT
WWW.2GIS.RUWWW.2GIS.RU
context === $data$data === $context.$data
BINDING-CONTEXT
WWW.2GIS.RUWWW.2GIS.RU
BINDINGS
<div class="contacts" data-bind="template: { name: 'firm-tpl', data: $data }"> <!-- Some code--></div>
WWW.2GIS.RUWWW.2GIS.RU
BINDING CONTEXT
$context
$element
● $data● $parent● $parentContext● $root● $index
WWW.2GIS.RUWWW.2GIS.RU
function initBalloon (options) { map.createBalloon({ point: options.point; content: options.template }); }
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
function initBalloon (options) { map.createBalloon({ point: options.point; content: options.template });
var container = $('#balloonContent'); ko.applyBindingsToNode(container , vm);}
BINDINGS
WWW.2GIS.RUWWW.2GIS.RU
КОГДА МНОГО "ЕСЛИ"
WWW.2GIS.RUWWW.2GIS.RU
this.hidePreloader = ko.computed(function(){ return this.firmsLoad() && this.geoLoad();});
<span id="preloader" data-bind="visible: !hidePreloader"></span>
КОГДА МНОГО "ЕСЛИ"
WWW.2GIS.RUWWW.2GIS.RU
Не наблюдайте один computed внутри другого
KO.COMPUTED
WWW.2GIS.RUWWW.2GIS.RU
1. Не наблюдайте один computed внутри другого
KO.COMPUTED
Не меняйте observable внутри computed
WWW.2GIS.RUWWW.2GIS.RU
1. Не наблюдайте один computed внутри другого2. Не меняйте observable внутри computed
KO.COMPUTED
Используйте computed только там, где это необходимо
WWW.2GIS.RUWWW.2GIS.RU
PLUGINS
WWW.2GIS.RUWWW.2GIS.RU
PLUGINS
knockout.address
WWW.2GIS.RUWWW.2GIS.RU
PLUGINS
WWW.2GIS.RUWWW.2GIS.RU
PLUGINS
window.location vm.myObservable
WWW.2GIS.RUWWW.2GIS.RU
PLUGINS
window.location vm.myObservable
WWW.2GIS.RUWWW.2GIS.RU
ko.linkObservableToUrl(vm.history, 'history');
https://github.com/SteveSanderson/knockout/wiki/Plugins
PLUGINS
WWW.2GIS.RUWWW.2GIS.RU
БОЛЬШИЕ ПРОЕКТЫ
107 22 18
ObservableComputed Observable
Array
WWW.2GIS.RUWWW.2GIS.RU
Functions
БОЛЬШИЕ ПРОЕКТЫ
200+ 107 22 18
WWW.2GIS.RUWWW.2GIS.RU
БОЛЬШИЕ ПРОЕКТЫ
200+ 107
22
18
13WWW.2GIS.RUWWW.2GIS.RU
Namespace.ViewModelModules.ourModule = { _observables: { ourObservable: "", ourObservableArray: [], ourComputed: function(){} },
_initModule: function(){/*initCode*/},
someProperty: 100500,
someFunction: function(){/*fBody*/}}
БОЛЬШИЕ ПРОЕКТЫ
WWW.2GIS.RUWWW.2GIS.RU
Namespace.ViewModelModules.ourModule = { _observables: { ourObservable: "", ourObservableArray: [], ourComputed: function(){} },
_initModule: function(){/*initCode*/},
someProperty: 100500,
someFunction: function(){/*fBody*/}}
WWW.2GIS.RU
БОЛЬШИЕ ПРОЕКТЫ
150
WWW.2GIS.RUWWW.2GIS.RU
IDE
data-bind=" //очень много //кода //который выглядит //как одна сплошная строка"
WWW.2GIS.RUWWW.2GIS.RU
IDE
WWW.2GIS.RUWWW.2GIS.RU
WWW.2GIS.RU
IDE
WWW.2GIS.RUWWW.2GIS.RU
АНАЛОГИ
- AngularJS- Backbone.js- Ember.js- ExtJS- CorMVC- AsanaLuna- ...
WWW.2GIS.RUWWW.2GIS.RU
ВОПРОСЫ?
WWW.2GIS.RUWWW.2GIS.RU