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
For a Future-Friendly Web
brad_frost
179
9.8k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Thoughts on Productivity
jonyablonski
69
4.7k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Side Projects
sachag
455
42k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
Raft: Consensus for Rubyists
vanstee
140
7k
Optimizing for Happiness
mojombo
379
70k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
281
13k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
5
290
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