Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Introduction to KnockoutJS
Search
romanych
March 27, 2012
0
71
Introduction to KnockoutJS
Материалы с тренинга о KnockoutJS - Введение
romanych
March 27, 2012
Tweet
Share
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
34
3.1k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.3k
The Art of Programming - Codeland 2020
erikaheidi
54
13k
Docker and Python
trallard
44
3.5k
How to Ace a Technical Interview
jacobian
277
23k
Scaling GitHub
holman
459
140k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.4k
Done Done
chrislema
184
16k
GitHub's CSS Performance
jonrohan
1031
460k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.5k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Transcript
Базовый тренинг по KnockoutJS Roman Gomolko
[email protected]
@romanych
Реальность в IT Никто не знает что надо делать, пока
это не сделано Программист Менджмент Бизнес
r
r
<svg> <circle id="circle" cx="110" cy="110" r="50" stroke="red" fill="transparent“ /> </svg>
<div> Radius: <input type="range" min="10" max="100" step="1" id="radius" value="50" /> Color: <input type="text" id="color" value="red" /> var circle = document.getElementById('circle'), radiusField = document.getElementById('radius'), colorField = document.getElementById('color'); radiusField.onchange = function () { circle.setAttribute('r', radiusField.value); } colorField.onchange = function () { circle.setAttribute('stroke', colorField.value); } Лучшая архитектура – её отсутствие
<svg> <circle id="circle" cx="110" cy="110" r="50" stroke="red" fill="transparent“ /> <text
id="radiusLabel"></text> </svg> Radius: <input type="range" min="10" max="100" step="1" id="radius" value="50" /> Color: <input type="text" id="color" value="red" /> var circle = document.getElementById('circle'), radiusField = document.getElementById('radius'); colorField = document.getElementById('color'); circle.onclick = function () { var c = random_color(); circle.setAttribute('stroke', colorField.value); colorField.value = c; } circle.onresize = function () { radiusField.value = circle.getAttribute('r'); radiusLabel.innerText = radiusField.value + 'px'; } radiusField.onchange = function () { circle.setAttribute('r', radiusField.value); radiusLabel.innerText = radiusField.value + 'px'; } colorField.onchange = function () { circle.setAttribute('stroke', colorField.value); } Лучшая архитектура – её отсутствие?
<svg> <circle id="circle" cx="110" cy="110" r="50" stroke="red" fill="transparent“ /> <text
id="radiusLabel"></text> </svg> Radius: <input type="range" min="10" max="100" step="1" id="radius" value="50" /> Color: <input type="text" id="color" value="red" /> var circle = document.getElementById('circle'), radiusField = document.getElementById('radius'); colorField = document.getElementById('color'); circle.onclick = function () { var c = random_color(); circle.setAttribute('stroke', c); colorField.value = c; } circle.onresize = function (e, r) { radiusField.value = r; radiusLabel.innerText = radiusField.value + 'px'; } radiusField.onchange = function () { circle.setAttribute('r', radiusField.value); radiusLabel.innerText = radiusField.value + 'px'; } colorField.onchange = function () { circle.setAttribute('stroke', colorField.value); } Взгляд на код со стороны
<svg> <circle id="circle" cx="110" cy="110" r="50" stroke="red" fill="transparent“ /> <text
id="radiusLabel"></text> </svg> Radius: <input type="range" min="10" max="100" step="1" id="radius" value="50" /> Color: <input type="text" id="color" value="red" /> var circle = $('#circle'), radiusField = $('#radius'), colorField = $('#color'); circle.click(function () { var c = random_color(); circle.attr('stroke', c); colorField.val(c); }); circle.bind(‘resize ‘, function (e, r) { radiusField.val(r); radiusLabel.text(radiusField.value + 'px'); }); radiusField.bind(‘change, function () { circle.attr('r', radiusField.value); radiusLabel.text(radiusField.value + 'px'); }); colorField.bind(‘change‘, function () { circle.attr('stroke', colorField.val()); }); jQuery нам поможет?
None
10
MVVM Model View View Model A ViewModel is basically a
value converter on steroids. Josh Smith
<svg> <circle cx="110" cy="110" r="?" stroke="?" fill="transparent“ onclick="setRandomColor()"/> <text>?</text> </svg>
Radius: <input type="range" min="10" max="100" step="1" value="?" /> Color: <input type="text" value="?" /> var ui= { radius: 50, color: 'red', setRandomColor: function() { ui.color = get_random_color() } } Взгляд на задачу со стороны MVVM
Knockout 13
<svg> <circle cx="200" cy="200" fill="transparent" data-bind="attr: { stroke: color, r:
radius}, event: { click: randomizeColor, resize: resize }" /> <text data-bind="text: radius() + 'px'"></text> </svg> Radius: <input type="range" min="10" max="100" step="1" data-bind="value: radius" /> Color: <input type="text" data-bind="value: color" /> var viewModel = { radius: ko.observable(50), color: ko.observable('red'), randomizeColor: function () { this.color(random_color()); }, resize: function(e, r) { this.radius(r); } }; ko.applyBindings(viewModel); Knockout в действии
MVVM vs MVC vs MVP
MVVM ViewModel • Color • Radius • SetRandomColor • Resize
MVC Model • Color • Radius Controller • ColorChanged • RadiusChanged • SetRandomColor MVVM vs MVC
MVVM is realtime MVC
- Не широко известый - Заставляет больше думать, где какой
код писать + Скорость разработки + Много reusable кода + Плюсы и минусы MVVM
Из чего стоит KnockoutJS Инфраструктура • Observables • Utility functions
Представление • Bindings • Templating 19
С чего начинается приложение var viewModel = { firstName: ko.observable(),
lastName: ko.observable() }; ko.applyBindings(viewModel); <form> <input type=“text” data- bind=“value: firstName , valueUpdate: ‘afterkeydown’” /> <input type=“text” data- bind=“value: lastName” /> </form> <label data-bind=“text: firstName”></label> <label data-bind=“text: lastName”></label> 20
Observables ko.observable() ko.observableArray() ko.computed() он же ko.dependentObservable() var firstName =
ko.observable() firstName() => undefined firstName(‘Casper’); firstName() => Casper var firstName = ko.observable(), lastName=ko.observable(); var fullName = ko.computed(function() { return firstName() + ' ' + lastName(); }); firstName('Richard'); lastName('Gere') fullName() => 'Richard Gere'; Observables позволяют следить за изменением значений 21
Пробуем ko.computed var viewModel = { firstName: ko.observable(), lastName: ko.observable()
}; viewModel.fullName = ko.computed(function() { return this.firstName() + ' ' + this.lastName(); }, viewModel); ko.applyBindings(viewModel); <input type="text" data- bind="value: firstName, valueUpdate: 'afterkeydown'" /> <input type="text" data- bind="value: lastName, valueUpdate: 'afterkeydown'" /> <span data-bind="text: fullName"></span> 22
Binding • Связывает ViewModel и View • Автоматическое обновление UI
• Может быть двусторонним или односторонним • Позволяет усложнять View не усложняя ViewModel 23
Стандартные Bindings Content & Appearance • text • html •
visible • css • style • attr Forms & Data • value • checked • enable • disable • options • selectedOptions … Control flow • if • ifnot • foreach • with Templating • template 24
Двустороннее и одностороннее связывание <input type=“text” data-bind=“value: firstName, valueUpdate: ‘afterkeydown’”
/> <input type=“text” data-bind=“value: firstName(), valueUpdate: ‘afterkeydown’” /> <span data-bind=“text: firstName”></span> 25
Пример binding’а ko.bindingHandlers['value'] = { 'init': function (element, valueAccessor, allBindingsAccessor)
{ element.onchange = function () { var modelValue = valueAccessor(); var elementValue = element.value; if (ko.isWriteableObservable(modelValue)) modelValue(elementValue); }; }, 'update': function (element, valueAccessor) { var newValue = ko.utils.unwrapObservable(valueAccessor()); var elementValue = element.value; var valueHasChanged = (newValue != elementValue); if (valueHasChanged) element.value = newValue; } }; 26
Препарируем ko.computed observable.subscribe(handler, bindingContext, event) var a = ko.observable(true), b
= ko.observable(false); a.subscribe(function(newA) { console.log(‘a changed to ‘, newA); }); b.subscribe(function(newB) { console.log(‘b changed to ‘, newB); }); var cmp = ko.computed(function() { console.log(‘Evaluate computed’); return a() || b(); }); 27
Препарируем ko.computed Evaluate computed // first time evaluation b(true) =>
b changed to true a(false) => a changed to false; Evaluate computed 28
Препарируем bindings ko.applyBindings() => for each node with data-bind: var
isFirstTime = true; ko.computed(function () { var bindings = eval("{" + element['data-bind'] + "}"); for (var binding in bindings) { if (ko.bindingHandlers[binding]) { if (isFirstTime) { isFirstTime = false; ko.bindingHandlers[binding].init(element, bindings[binding], bindings); } ko.bindingHandlers[binding].update(element, bindings[binding], bindings); } } }); 29
Полезные функции • ko.utils.unwrapObservable() • ko.isObservable() • ko.isSubscribable() • ko.isWriteableObservable()
30
Пример с фильтрацией grid’а 31