Knockoutjs на примере 2ГИС-Онлайн

80
ИЛЬЯ ТАРАТУХИН KNOCKOUT.js НА ПРИМЕРЕ 2ГИС-ОНЛАЙН

description

 

Transcript of Knockoutjs на примере 2ГИС-Онлайн

Page 1: Knockoutjs на примере 2ГИС-Онлайн

ИЛЬЯ ТАРАТУХИН

KNOCKOUT.js НА ПРИМЕРЕ

2ГИС-ОНЛАЙН

Page 2: Knockoutjs на примере 2ГИС-Онлайн

ДОКЛАДЧИК

Разрабатывал АСУ ТП

для горно-шахтного

оборудования

Спикер CodeFest

2012

API справочника

>5 млн API карт

>8 млн Карты 2ГИС

>3 млн

С 2011 года работаю в 2ГИС

WWW.2GIS.RU

Page 3: Knockoutjs на примере 2ГИС-Онлайн
Page 4: Knockoutjs на примере 2ГИС-Онлайн
Page 5: Knockoutjs на примере 2ГИС-Онлайн
Page 6: Knockoutjs на примере 2ГИС-Онлайн
Page 7: Knockoutjs на примере 2ГИС-Онлайн
Page 8: Knockoutjs на примере 2ГИС-Онлайн

WWW.2GIS.RU

Пользователь

2ГИС Онлайн

API Справочника

АРХИТЕКТУРА WEB-APP

Page 9: Knockoutjs на примере 2ГИС-Онлайн

АРХИТЕКТУРА CLIENT-SIDE APP

Пользователь

2ГИС Онлайн

API

Транспорта

API

пробок

API <Место для

вашего сервиса>

API

Справочник

API

Карт +1

WWW.2GIS.RU

Page 10: Knockoutjs на примере 2ГИС-Онлайн

DOM НА КЛИЕНТЕ

WWW.2GIS.RU

Page 11: Knockoutjs на примере 2ГИС-Онлайн

DOM НА КЛИЕНТЕ

var newDiv = document.createElement('div');

newDiv.className = 'my-class';

newDiv.id = 'my-id';

newDiv.innerHTML = 'Привет, мир!';

$('#container').appendChild(newDiv);

Привет, мир!

WWW.2GIS.RU

Page 12: Knockoutjs на примере 2ГИС-Онлайн

WHERE IS

Page 13: Knockoutjs на примере 2ГИС-Онлайн

ШАБЛОНИЗАТОРЫ

jQueryTemplate

Mustache

Underscore.js

Шаблонизатор резига

Pure

WWW.2GIS.RU WWW.2GIS.RU

Page 14: Knockoutjs на примере 2ГИС-Онлайн

СОБЫТИЯ

.firmShort

.firmFull #firmList

WWW.2GIS.RU WWW.2GIS.RU

Page 15: Knockoutjs на примере 2ГИС-Онлайн

СОБЫТИЯ

$("#firmTemplate").tmpl(someData)

.appendTo("#firmList");

$('.firmShort').live({

click: function() {

showFirmCard(this);

}

});

$('.firmFull').live({

click: function() {

hideFirmCard(this);

}

});

WWW.2GIS.RU WWW.2GIS.RU

Page 16: Knockoutjs на примере 2ГИС-Онлайн

СОБЫТИЯ

WWW.2GIS.RU WWW.2GIS.RU

Page 17: Knockoutjs на примере 2ГИС-Онлайн
Page 18: Knockoutjs на примере 2ГИС-Онлайн

KNOCKOUT

WWW.2GIS.RU WWW.2GIS.RU

Page 19: Knockoutjs на примере 2ГИС-Онлайн

ПОЧЕМУ KNOCKOUT?

Активно развивается

WWW.2GIS.RU WWW.2GIS.RU

Page 20: Knockoutjs на примере 2ГИС-Онлайн

• Активно развивается

ПОЧЕМУ KNOCKOUT?

Удобное разделение

логики и шаблонов

WWW.2GIS.RU WWW.2GIS.RU

Page 21: Knockoutjs на примере 2ГИС-Онлайн

• Активно развивается

• Удобное разделение логики и шаблонов

ПОЧЕМУ KNOCKOUT?

Функционален, есть

декларативные биндинги

WWW.2GIS.RU WWW.2GIS.RU

Page 22: Knockoutjs на примере 2ГИС-Онлайн

• Активно развивается

• Удобное разделение логики и шаблонов

• Функционален, есть декларативные

биндинги

ПОЧЕМУ KNOCKOUT?

Низкий порог вхождения

WWW.2GIS.RU WWW.2GIS.RU

Page 23: Knockoutjs на примере 2ГИС-Онлайн
Page 24: Knockoutjs на примере 2ГИС-Онлайн

MVVM

View Model

ViewModel

UI Logic Business Logic

Application Logic

WWW.2GIS.RU WWW.2GIS.RU

Page 25: Knockoutjs на примере 2ГИС-Онлайн

KNOCKOUT

WWW.2GIS.RU WWW.2GIS.RU

Page 26: Knockoutjs на примере 2ГИС-Онлайн

<div class="dg-search-result-header">

<span data-bind="text:

what_text"></span>,

<span data-bind="text:

where_text"></span></div>

KNOCKOUT

WWW.2GIS.RU WWW.2GIS.RU

Page 27: Knockoutjs на примере 2ГИС-Онлайн

function vm() {

this.what_text = ko.observable('');

}

ko.applyBindings(new vm());

...

vm.what_text(response.what);

<span data-bind="text: what_text"></span>

KO.OBSERVABLE

WWW.2GIS.RU WWW.2GIS.RU

Page 28: Knockoutjs на примере 2ГИС-Онлайн

МАССИВЫ

WWW.2GIS.RU WWW.2GIS.RU

Page 29: Knockoutjs на примере 2ГИС-Онлайн

response.result = [

{

firmName = 'Завод №1',

...

},

{

firmName = 'Завод №2';

...

}]

МАССИВЫ

WWW.2GIS.RU WWW.2GIS.RU

Page 30: Knockoutjs на примере 2ГИС-Онлайн

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.RU WWW.2GIS.RU

Page 31: Knockoutjs на примере 2ГИС-Онлайн

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 32: Knockoutjs на примере 2ГИС-Онлайн

<div class="dg-search-result-header">

<span data-bind="text:

what_text"></span>,

<span data-bind="text:

where_text"></span></div>

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 33: Knockoutjs на примере 2ГИС-Онлайн

BINDINGS

- Текст и стиль блока

- Control flow

- Работа с формами

- Шаблонизация

- <место для ваших идей>

WWW.2GIS.RU WWW.2GIS.RU

Page 34: Knockoutjs на примере 2ГИС-Онлайн

.firmShort

.firmFull

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

#firmList

Page 35: Knockoutjs на примере 2ГИС-Онлайн

<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.RU WWW.2GIS.RU

Page 36: Knockoutjs на примере 2ГИС-Онлайн

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 37: Knockoutjs на примере 2ГИС-Онлайн

data-bind="visible: isVisible,

click: toggleVisibility"

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 38: Knockoutjs на примере 2ГИС-Онлайн

data-bind="visible: isVisible,

click: toggleVisibility"

toggleVisibility = function() {

this.isVisible(!this.isVisible());}

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 39: Knockoutjs на примере 2ГИС-Онлайн
Page 40: Knockoutjs на примере 2ГИС-Онлайн

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.RU WWW.2GIS.RU

Page 41: Knockoutjs на примере 2ГИС-Онлайн

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.RU WWW.2GIS.RU

Page 42: Knockoutjs на примере 2ГИС-Онлайн

data-bind="animateVisible: isVisible,

click: toggleVisibility"

toggleVisibility = function() {

this.isVisible(!this.isVisible());}

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 43: Knockoutjs на примере 2ГИС-Онлайн
Page 44: Knockoutjs на примере 2ГИС-Онлайн
Page 45: Knockoutjs на примере 2ГИС-Онлайн

<script type="text/my-tpl" id="firm-tpl">

//firm template code</script>

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 46: Knockoutjs на примере 2ГИС-Онлайн

<script type="text/my-tpl" id="catalog-tpl">

//some template code

<div data-bind="template: {

name: 'firm-tpl',

foreach: firms

}"></div>

</script>

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 47: Knockoutjs на примере 2ГИС-Онлайн

BINDINGS

Page 48: Knockoutjs на примере 2ГИС-Онлайн

BINDING-CONTEXT

vm

vm.firms[n]

WWW.2GIS.RU WWW.2GIS.RU

Page 49: Knockoutjs на примере 2ГИС-Онлайн

ПЕЧАТЬ

WWW.2GIS.RU WWW.2GIS.RU

Page 50: Knockoutjs на примере 2ГИС-Онлайн

<script type="text/my-tpl" id="print-tpl">

//some template code

<div data-bind="template: {

name: 'firm-tpl',

foreach: firms,

templateOptions: {

isPrint: 1

}

}"></div>

</script>

ПЕЧАТЬ

WWW.2GIS.RU WWW.2GIS.RU

Page 51: Knockoutjs на примере 2ГИС-Онлайн

BINDINGS

<div class="phone-number"

data-bind="visible:

$context.isPrint)">

<!-- Some code-->

</div>

WWW.2GIS.RU WWW.2GIS.RU

Page 52: Knockoutjs на примере 2ГИС-Онлайн

BINDINGS

<div class="contacts"

data-bind="template: {

name: 'firm-tpl',

data: $data,

templateOptions: {

isPrint: $context.isPrint

}

}">

<!-- Some code-->

</div>

WWW.2GIS.RU WWW.2GIS.RU

Page 53: Knockoutjs на примере 2ГИС-Онлайн

$context

$data

templateOptions

BINDING CONTEXT

WWW.2GIS.RU WWW.2GIS.RU

Page 54: Knockoutjs на примере 2ГИС-Онлайн

BINDING CONTEXT

$context

$data

templateOptions

• $parent

• $parentContext

• $root

• $index

• $element

WWW.2GIS.RU WWW.2GIS.RU

Page 55: Knockoutjs на примере 2ГИС-Онлайн
Page 56: Knockoutjs на примере 2ГИС-Онлайн

function initBalloon (options) {

map.createBalloon({

point: options.point;

content: options.template

}); }

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 57: Knockoutjs на примере 2ГИС-Онлайн

function initBalloon (options) {

map.createBalloon({

point: options.point;

content: options.template

});

var container = $('#balloonContent');

ko.applyBindingsToNode(container ,

vm);}

BINDINGS

WWW.2GIS.RU WWW.2GIS.RU

Page 58: Knockoutjs на примере 2ГИС-Онлайн

КОГДА МНОГО "ЕСЛИ"

WWW.2GIS.RU WWW.2GIS.RU

Page 59: Knockoutjs на примере 2ГИС-Онлайн

this.showPreloader = ko.computed(function(){

return this.firmsLoad() &&

this.geoLoad();});

<span id="preloader"

data-bind="visible: showPreloader">

</span>

КОГДА МНОГО "ЕСЛИ"

WWW.2GIS.RU WWW.2GIS.RU

Page 60: Knockoutjs на примере 2ГИС-Онлайн

Не наблюдайте один computed

внутри другого

KO.COMPUTED

WWW.2GIS.RU WWW.2GIS.RU

Page 61: Knockoutjs на примере 2ГИС-Онлайн

1. Не наблюдайте один computed внутри другого

KO.COMPUTED

Не меняйте observable внутри

computed

WWW.2GIS.RU WWW.2GIS.RU

Page 62: Knockoutjs на примере 2ГИС-Онлайн

1. Не наблюдайте один computed внутри другого

2. Не меняйте observable внутри computed

KO.COMPUTED

Используйте computed только там,

где это необходимо

WWW.2GIS.RU WWW.2GIS.RU

Page 63: Knockoutjs на примере 2ГИС-Онлайн

PLUGINS

WWW.2GIS.RU WWW.2GIS.RU

Page 64: Knockoutjs на примере 2ГИС-Онлайн

PLUGINS

knockout.address

WWW.2GIS.RU WWW.2GIS.RU

Page 65: Knockoutjs на примере 2ГИС-Онлайн

PLUGINS

knockout.address

window.location vm.myObservable

ko.linkObservableToUrl(vm.history, 'history');

WWW.2GIS.RU WWW.2GIS.RU

Page 66: Knockoutjs на примере 2ГИС-Онлайн

https://github.com/SteveSanderson/knockout/wiki/Plugins

PLUGINS

WWW.2GIS.RU WWW.2GIS.RU

Page 67: Knockoutjs на примере 2ГИС-Онлайн
Page 68: Knockoutjs на примере 2ГИС-Онлайн
Page 69: Knockoutjs на примере 2ГИС-Онлайн

БОЛЬШИЕ ПРОЕКТЫ

107 22 18

Observable

Computed Observable

Array

WWW.2GIS.RU WWW.2GIS.RU

Page 70: Knockoutjs на примере 2ГИС-Онлайн

Functions

БОЛЬШИЕ ПРОЕКТЫ

200+ 107 22 18

WWW.2GIS.RU WWW.2GIS.RU

Page 71: Knockoutjs на примере 2ГИС-Онлайн

БОЛЬШИЕ ПРОЕКТЫ

200+ 107

22

18

13

WWW.2GIS.RU WWW.2GIS.RU

Page 72: Knockoutjs на примере 2ГИС-Онлайн

Namespace.ViewModelModules.<ourModule> = {

_observables: {

<ourObservable>: <defaultData>,

<ourComputed>:

function(){/*computedCode*/}

},

<someProperty>: 100500,

_initModule: function(){/*initCode*/},

<function>: function(){/*fBody*/}}

БОЛЬШИЕ ПРОЕКТЫ

WWW.2GIS.RU WWW.2GIS.RU

Page 73: Knockoutjs на примере 2ГИС-Онлайн

Namespace.ViewModelModules.<ourModule> = {

_observables: {

<ourObservable>: <defaultData>,

<ourComputed>:

function(){/*computedCode*/}

},

<someProperty>: 100500,

_initModule: function(){/*initCode*/},

<function>: function(){/*fBody*/}}

WWW.2GIS.RU

БОЛЬШИЕ ПРОЕКТЫ

150

WWW.2GIS.RU WWW.2GIS.RU

Page 74: Knockoutjs на примере 2ГИС-Онлайн

IDE

data-bind="

//очень много

//кода

//который выглядит

//как одна сплошная строка

"

WWW.2GIS.RU WWW.2GIS.RU

Page 75: Knockoutjs на примере 2ГИС-Онлайн

IDE

WWW.2GIS.RU WWW.2GIS.RU

Page 76: Knockoutjs на примере 2ГИС-Онлайн

WWW.2GIS.RU

IDE

WWW.2GIS.RU WWW.2GIS.RU

Page 77: Knockoutjs на примере 2ГИС-Онлайн

АНАЛОГИ

- AngularJS

- Backbone.js

- Ember.js

- ExtJS

- CorMVC

- AsanaLuna

- ...

WWW.2GIS.RU WWW.2GIS.RU

Page 78: Knockoutjs на примере 2ГИС-Онлайн

ВОПРОСЫ?

WWW.2GIS.RU WWW.2GIS.RU

Page 79: Knockoutjs на примере 2ГИС-Онлайн
Page 80: Knockoutjs на примере 2ГИС-Онлайн