14
Knockout JS là thư viên javascript giúp bạn tạo các ứng dụng linh hoạt và mượt mà với tầng Data Model bên dưới. Ví dụ khi bạn có một giao diện và cần phải cập nhật dữ liệu động từ View xuống Model hoặc tự động cập nhật lại View mỗi khi Model thay đổi hoặc Model với Model (người ta còn hay gọi là 2 ways binding), thì Knockout JS sẽ giúp bạn thực hiện tính năng đó một cách đơn giản và dễ dàng bảo trì sau này. Để sử dụng thư viện này, các bạn hãy download tại: http://knockoutjs.com/downloads/index.html Hoặc sử dụng Bower tool: bower install knockout Trước khi chúng ta tìm hiểu Observables thì mình xin giới thiệu sơ về mô hình MVVM. Model View View-Model (MVVM) là một Design Pattern giúp bạn phát triển ứng dụng linh hoạt bằng cách tách biệt ra 3 phần là Model, View và View Model. Model: là phn cha dliu ca ng dụng và nó được tách riêng v i phn giao diện người dùng (UI). View: là phần được trình bày ra cho người dùng đầu cui. Nó có nhi m v hin ththông tin t model, người dùng có thtương tác với view (nhấn nút login trên màn hình) để truyn mnh lnh xuống cho view model để cp nht model và view có thđược cp nht thông tin khi trng thái thông tin trong model thay đổi (ta còn gọi là cơ chế binding 2 way). Binding 2 way không chdin ra gia view và model, nó còn di n ra gia các model v i nhau. View Model: là phn mô t dliệu và các thao tác trên UI. Lưu ý rằng nó không phi là phn dliu trong Model và c ng không phải là UI (Button, Checkbox, Label…) trong View, mà nó quản lý phn dliệu mà người dùng đang tương tác. Activating Knockout và Observables Để hiểu về tính năng này mình sẽ trình bày một ví dụ đơn giản để các bạn dễ dàng hiểu đư ợc. Giờ thì chúng ta bắt đầu nhé: http://js/jquery-2.1.3.js http://js/knockout-3.3.0.js http://js/bootstrap.js Chúng ta thêm các Sc ript như trên để có thể sử dụng thư viên Knockout. Ở trên các bạn có thể thêm hoăc bỏ qua thư viện Bootstrap (Bootstrap yêu cầu cần có thư viện jQuery), vì vậy các bạn nhớ include luôn jQuery nhé. Để activating Knockout và Web Browser có thể hiểu được cú pháp của nó, các bạn hãy chèn đoạn script như bên dưới:

Tổng quan về knockout js

Embed Size (px)

Citation preview

Knockout JS là thư viên javascript giúp bạn tạo các ứng dụng linh hoạt và mượt mà với tầng Data

Model bên dưới. Ví dụ khi bạn có một giao diện và cần phải cập nhật dữ liệu động từ View xuống

Model hoặc tự động cập nhật lại View mỗi khi Model thay đổi hoặc Model với Model (người ta còn hay

gọi là 2 ways binding), thì Knockout JS sẽ giúp bạn thực hiện tính năng đó một cách đơn giản và dễ

dàng bảo trì sau này.

Để sử dụng thư viện này, các bạn hãy download tại: http://knockoutjs.com/downloads/index.html

Hoặc sử dụng Bower tool: bower install knockout

Trước khi chúng ta tìm hiểu Observables thì mình xin giới thiệu sơ về mô hình MVVM.

Model View View-Model (MVVM) là một Design Pattern giúp bạn phát triển ứng dụng linh hoạt bằng

cách tách biệt ra 3 phần là Model, View và View Model.

Model: là phần chứa dữ liệu của ứng dụng và nó được tách riêng với phần giao diện người

dùng (UI).

View: là phần được trình bày ra cho người dùng đầu cuối. Nó có nhiệm vụ hiển thị thông tin từ

model, người dùng có thể tương tác với view (nhấn nút login trên màn hình) để truyền mệnh

lệnh xuống cho view model để cập nhật model và view có thể được cập nhật thông tin khi trạng

thái thông tin trong model thay đổi (ta còn gọi là cơ chế binding 2 way). Binding 2 way không chỉ

diễn ra giữa view và model, nó còn diễn ra giữa các model với nhau.

View Model: là phần mô tả dữ liệu và các thao tác trên UI. Lưu ý rằng nó không phải là phần dữ

liệu trong Model và củng không phải là UI (Button, Checkbox, Label…) trong View, mà nó quản

lý phần dữ liệu mà người dùng đang tương tác.

Activating Knockout và Observables

Để hiểu về tính năng này mình sẽ trình bày một ví dụ đơn giản để các bạn dễ dàng hiểu được.

Giờ thì chúng ta bắt đầu nhé:

http://js/jquery-2.1.3.js

http://js/knockout-3.3.0.js

http://js/bootstrap.js

Chúng ta thêm các Script như trên để có thể sử dụng thư viên Knockout. Ở trên các bạn có thể thêm

hoăc bỏ qua thư viện Bootstrap (Bootstrap yêu cầu cần có thư viện jQuery), vì vậy các bạn nhớ

include luôn jQuery nhé.

Để activating Knockout và Web Browser có thể hiểu được cú pháp của nó, các bạn hãy chèn đoạn

script như bên dưới:

ko.applyBindings(viewModel);

Có thể để đoạn Script trên ở cuối trang HTML hoặc đầu trang và nằm trong DOM ready handler của

jQuery

$(function() {

// Document is ready

});

Cách thứ 2 để activate Knockout:

ko.applyBindings(<viewModel>, [DOM]);

Dòng lệnh trên gồm 2 tham số, tham số đầu tiên thể hiển View Model mà các bạn muốn thao tác trên

nó, với tham số thứ 2 là optional, các bạn có thể truyền vào hoặc không, tham số này thể hiện phần

DOM để Knockout tìm thuộc tính data-bind (thuộc tính dùng để binding trong Knockout), và View

Model tương ứng sẽ làm việc với phần DOM tương ứng mà chúng ta khai báo.

Ví dụ:

ko.applyBindings(viewModel, document.getElementById("elementID"));

Cách activate này được dùng khi bạn có nhu cầu dùng nhiều View Model trên nhiều phần DOM khác

nhau trên trang HTML.

Bắt đầu mình sẽ trình bày cách bind data đơn giản từ View Model lên View.

Đầu tiên chúng ta cần khai báo View Model, để khai báo View Model đơn giản trong Knockout, chúng

ta chỉ cần khai báo một object javascript.

var viewModel = {

name: ‘Truc Nguyen’,

age: 23

};

Sau đó khai báo một View đơn giản:

Name: <span data-bind="text: name"></span><br>

Age: <span data-bind="text: age"></span>

Sau đó activate Knockout bằng cách:

ko.applyBindings(viewModel);

Observable trong KnockoutJS

Một trong những tính năng quan trọng của Knockout là tự động cập nhật dữ liệu lên View khi các

thuộc tính trong View Model thay đổi. Chắc chắn các bạn đang thắc mắc làm sao View có thể biết mà

cập nhật lại dữ liệu khi View Model thay đổi, thì câu trả lời chính là Observables. Có nghĩa là chúng ta

cần khai báo thuộc tính mà chúng ta có nhu cầu tự động cập nhật dữ liệu lên View là observable, vì

observable là một đối tượng javascript đặc biệt nên các thuộc tính nào được khai báo là observable

đều sẽ thông báo cho các thuộc tính binding trên View về sự thay đổi đó và tự động cập nhật lại dữ

liệu lên View.

var viewModel = {

name: ko.observable('Truc Nguyen'),

age: ko.observable(23)

};

Trong View chúng ta không cần thay đổi gì, sự khác biệt là khi name và age thay đổi, thì dữ liệu trên

View sẽ được cập nhất tương ứng. Mình đã trình bày xong Knockout và Observables.

Tổng quan về Knockout js

Giới thiệu chung

Mô hình của Knockout js(MVVM)

Hướng dẫn cài đặt

Observables trong Knockout js

Giới thiệu chung

Knockout(KO) là một thư viện của Javascript, nó giúp bạn tạo, hiển thị

hay hiệu chỉnh User Interface(UI) với một data model được định nghĩa

sẵn. Bất cứ khi nào bạn có phần thay đổi(thay đổi về action của user

hay dữ liệu nội tại thay đổi) trong UI thì KO có thể giúp bạn thực hiện

nó một cách đơn giản, và dễ kiểm soát

Các tính năng nổi bật của KO

-Theo dõi tự động sự phụ thuộc trường này vào trường khác - Tự

động cập nhật đúng phần giao diện khi có sự thay đổi phần tử đang

được theo dõi. -Khai báo các ràng buộc với dữ liệu - một cách đơn

giản để kết nối các phần trong UI đến với dữ liệu trong model của bạn.

-Lập trình mở rộng - thực hiện các behavior tùy chọn cũng như việc

khai báo ràng buộc mới cho việc tái sử dụng trong một vài dòng code.

Một số lợi ích khác:

Thư viện thuần Javascript - Làm việc tốt với nhiều server hoặc.

Làm việc tốt với nhiều trình duyệt - (IE 6+, Firefox 2+,

Chrome, Safari, ...).

Thích ứng tốt - Có thể dễ dàng xác định được các chức năng của

nó trên các trình duyệt và các nền tảng mới.

Mô hình của knockout js

Developers thường quen với mô hình MVC rất điển hình trong các

framework điển hình của quá trình phát triển ứng dụng web. Tuy nhiên

KO sử dụng mô hình MVVM (Model-View-ViewModel), nó là một biến

thể của MVC. Mô hình MVVM gồm 3 phần chính là: Model, View,

ViewModel. View và Model có chức năng vai trò như trong mô hình

MVC. ViewModel trong MVVM như là một controller đặc biệt, nó cung

cấp các hoạt động, logic cần thiết để view có thể lấy được dữ liệu thuận

tiện. ViewModel được coi là một view trừu tượng, nó chứa trạng thái và

các bihavior của view. Tuy nhiên ViewModel không chứa các tham chiếu

đến thành phần của UI và không biết gì về các thành phần nhìn thấy

của View. Do đó có sự tách biệt rõ ràng giữa View và ViewModel. Hay

nói một cách khác là View layer là sự ánh xạ của ViewModel

Mô hình MVVM được mô tả đơn giản như sau:

Cụ thể tất cả các quá trình diễn ra qua các bước sau:

Mỗi user nhấn vào một nút trên màn hình (thực hiện một action).

Một sự kiện bắn ra chất kết dính (binder).

Chất kết dính tìm action logic tương ứng trong ViewModel và thực

thi nó.

Action logic đó truy cập dữ liệu trong Model layer và cập nhật tính

năng tương ứng của ViewModel đó.

ViewModel thông báo cho binder đó một vài tính năng đã được

thay đổi.

Các tính năng vừa được cập nhật là nhờ việc tải dữ liệu từ binder

trong ViewModel.

Binder sau đó cập nhật các thành phần UI tương ứng để cung cấp

các phản hồi trực quan cho user.

Hướng dẫn cài đặt

Trước tiên cài Bower package

sudo npm install -g bower

bower install knockout

Để sử dụng đơn giản chỉ cần nhúng vào thẻ ở một nơi nào đó trong

code HTML. Ví dụ như sau

<script type='text/javascript' src='knockout-3.2.0.js'></script>

Observables

Tạo view models với observables

Như vậy về cơ bản, knockout js là một mô hình thiết kế cho việc xây

dựng giao diện người dùng một cách đơn giản mà rất dễ dàng cho việc

chỉnh sửa, cập nhật dữ liệu ngay trên view. Để tạo một view model với

KO, bạn cần phải khai báo một JavaScript Object. Ví dụ (sử dụng

framework laravel 4x):

Kết quả output sẽ như

sau:

Trong view rõ ràng ta thấy rằng thuộc tính data-bind không có trong

HTML, nó chính là thuộc tính của KO, chính vì HTML không hiểu được

nó nên bạn cần phải active nó trong <script>

ko.applyBindings(myViewModel);

Tuy nhiên, đó mới chỉ là việc làm thế nào để bạn create một view

model cơ bản và hiển thị chúng bằng cách dùng binding, lợi ích lớn

nhất của KO là tự động cập nhật UI khi view model thay đổi. Và làm

thế nào mà KO có thể biết phần view model của bạn thay đổi. Câu trả

lời là bạn cần phải khai báo các thuộc tính của model bằng observabels,

bởi vì chỉ có Javascript object mới thông báo được cho người theo dõi

biết về những thay đổi đó, và có thể tự động tìm thấy sự phụ thuộc

Làm việc với observables arrays

Nếu bạn muốn phát hiện và phản hồi lại những thay đổi của một

object, thì bạn dùng observables. Còn nếu bạn muốn phát hiện và

phản hồi lại những thay đổi của tập hợp nhiều thứ thì bạn

dùng observableArray, nó được sử dụng khá phổ biến trong KO.

Thường thì khi put một object trong một observableArray thì sẽ

không tạo được toàn bộ các thuộc tính cho bản thân mỗi một

observable. Tất nhiên là bạn hoàn toàn có thể tạo ra nhiều thuộc tính

cho observable mà bạn mong muốn Nếu bạn muốn mảng observable

khởi tạo bằng rỗng, thì bạn khởi tạo nó theo cấu trúc như sau:

// This observable array initially contains three objects

var anotherObservableArray = ko.observableArray([

{ name: "Bungle", type: "Bear" },

{ name: "George", type: "Hippo" },

{ name: "Zippy", type: "Unknown" }

]);

alert('The length of the array is ' + myObservableArray().length);

alert('The first element is ' + myObservableArray()[0]);

Tuy nhiên observableArray có nhiều tiện ích hơn so với native

JavaScript array, bởi vì:

Làm việc tốt trên mọi trình duyệt. (Ví dụ, hàm của native

JavaScript indexOf không làm việc được với IE 8 trở về trước tuy

nhiên KO’s indexOf làm việc được tốt)

Hàm thay đổi nội dung của một array như push và splice, phương

thức của KO thì tự động trigger tất cả sự kiện trên UI và qua xử

lý sẽ tự động cập nhật lại UI.

Cú pháp của KO có rất nhiều convenient. Để gọi phương

thức push của KO, viếtmyObservableArray.push(...). Đây là cách hay

hơn 1 chút so với việc gọi ẩn array push method với việc

viếtmyObservableArray().push(...).

Các thao tác với observableArray

myObservableArray.push('Some new value') Thêm một item mới vào

cuối array

myObservableArray.pop() xóa bỏ giá trị cuối cùng của array và return

myObservableArray.unshift('Some new value') inserts một new item ở

vị trí đầu tiên của array

myObservableArray.shift() xóa bỏ giá trị đầu tiên của array và

returns nó

myObservableArray.reverse() đảo thứ tự của array

myObservableArray.sort() sắp xếp nội dung của array.

o mặc định là sắp xếp theo alphabetical, tuy nhiên bạn có thể

thêm vào các tùy chọn để sắp xếp. Ví dụ, để sắp xếp một

mảng ‘person’ objects theo last name, bạn có thể viết như

saumyObservableArray.sort(function(left, right) { return

left.lastName == right.lastName ? 0 : (left.lastName <

right.lastName ? -1 : 1) })

myObservableArray.splice() xóa và return lại số của thành phần bắt

đầu từ vị trí đánh index. Ví dụ,myObservableArray.splice(1, 3) xóa 3

thành phần bắt đầu từ vị trí index số 1 (tức là xóa thành phần 2,

3, 4) and và return chúng là một mảng.

Một số tiện ích khác mà Javascript array không có như sau:

myObservableArray.remove(someItem) xóa toàn bộ giá trị bằng

với someItem and returns chúng về một array

myObservableArray.remove(function(item) { return item.age < 18

}) xóa toàn bộ giá trị củaage mà nhỏ hơn 18, và returns chúng là

một array

myObservableArray.removeAll(['Chad', 132, undefined]) xóa toàn bộ

giá trị 'Chad', 123, or undefined và returns chúng là một array

myObservableArray.removeAll() xóa toàn bộ giá trị và returns chúng

là một array

Ở phần một chúng ta đã biết tổng quan về knockout js (KO), cách tạo

viewModel với observables và làm việc với observable arrays. Phần này

chúng ta tiếp tục tìm hiểu về một trong những thành phần khá quan

trọng của KO đó là Biding.

Binding trong KO có một số điểm đáng chú ý như sau:

1. Controlling text và appearance

2. Control flow

Phần 1: Controlling text và Appearance

a. The visible binding

Thuộc tính visible binding là nguyên nhân làm cho các thành phần kết

hợp của DOM trở nên ẩn đi hoặc có thể nhìn thấy được thông qua giá

trị mà bạn pass trong binding. Ví dụ:

PHP

<div data-bind="visible: shouldShowMessage">

You will see this message only when "shouldShowMessage" holds a true value.

</div>

<script type="text/javascript">

var viewModel = {

shouldShowMessage: ko.observable(true) // Message initially visible

};

viewModel.shouldShowMessage(false); // ... now it's hidden

viewModel.shouldShowMessage(true); // ... now it's visible again

</script>

Khi observable parameter nhận giá trị boolean là false, hoặc giá trị kiểu

số là 0, hoặc null hoặc undefined thì binding sẽ

set yourElement.style.display là none tức là nó sẽ bị ẩn và nó được ưu

tiên hơn bất kì style display nào mà bạn dùng css để định nghĩa.

Khi observaale parameter nhận giá trị boolean là true, hoặc một object,

array không null thì binding sẽ khửyourElement.style.display bởi vì giá trị

của nó trở nên có thể nhìn thấy được.

b. The text binding

Dùng để hiển thị text của biến hay một trường nào đó trong database,

text binding sử dụng tiện lợi với rất nhiều loại thẻ của HTML như

thẻ <div>, <i>, <span>, ... Một lợi thế khác được xét trong ví dụ như sau:

PHP

Today's message is: <span data-bind="text: myMessage"></span>

<script type="text/javascript">

var viewModel = {

myMessage: ko.observable() // Initially blank

};

viewModel.myMessage("Hello, world!"); // Text appears </script>

Nếu parameter là một giá trị observablue thì binding sẽ update giá trị

của text ở bất kì nơi nào khi mà giá trị của text đó được thay đổi

c. The "css" binding

Sử dụng css binding người dùng có thể add hoặc remove một hoặc

nhiều class static hoặc dynamic. Ví dụ về static classes

PHP

<div data-bind="css: { profitWarning: currentProfit() < 0 }">

Profit Information

</div>

<script type="text/javascript">

var viewModel = {

currentProfit: ko.observable(150000) // Positive value, so initially we don't apply the "profitWarning" class

};

viewModel.currentProfit(-50); // Causes the "profitWarning" class to be applied </script>

Bằng cách này CSS class profitWarning sẽ active khi giá

trị currentProfit nhỏ hơn 0 và khi giá trị biến này bằng hoặc lớn hơn 0

thì class profitWarning sẽ được tự động remove .

d. The style binding

Sử dụng style binding trong KO rất tiện dụng, nó có thể add hoặc

remove một hay nhiều giá trị style kết hợp với thành phần của DOM

Bạn cũng có thể pass một JavaScript object trong thuộc tính tên tương

ứng với tên của style và giá trị cũng tương ứng với giá trị của style mà

bạn đã định nghĩa. Ví dụ:

PHP

bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">

Profit Information

</div>

<script type="text/javascript">

var viewModel = {

currentProfit: ko.observable(150000) // Positive value, so initially black

};

viewModel.currentProfit(-50); // Causes the DIV's contents to go red

</script>

style.color nhận giá trị red ở bất cứ nơi nào khi currentProfit có giá trị

nhỏ hơn 0 và nhận giá trị là blackkhi currentProfit có giá trị lớn hơn 0.

Ngoài ra bạn cũng có thể đặt được nhiều style trong cùng một thẻ. Ví

dụ

PHP

<div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black', fontWeight: isSevere() ? 'bold' : '' }" >...</div>

Nếu parameter của bạn tham chiếu đến một giá trị observable thì

binding sẽ update style ở bất cứ nơi nào mà observable có giá trị thay

đổi. Một lưu ý: khi đặt style name của bạn cần chú ý một số style bị

trùng với JavaScript định danh và bạn phải dùng JavaScript name cho

những style đó:

margin-bottom => marginBottom

margin-left => marginLeft

margin-right => marginRight

margin-top => marginTop

color => backgroundColor

list-style => listStyle

font-family => fontFamily

font-style => fontStyle

font-variant => fontVariant

font-weight => fontWeight

line-height => lineHeight

text-align => textAlign

text-decoration => textDecoration

text-indent => textIndent

text-transform => textTransform

vertical-align => verticalAlign

e. The "attr" binding

"attr" binding cung cấp một cách chung nhất về tập các giá trị của rất

nhiều thuộc tính kết hợp với các thành phần của DOM. Điều này rất tiện

lợi cho việc bạn sử dụng các thuộc tính title, img, href, ... trong giá trị

view model mà bạn đã định nghĩa. Và cũng giống như bất kì binding

nào khác thì sử dụng "attr" giá trị của thuộc tính cũng sẽ update một

cách tự động ở bất cứ đâu khi thuộc tính model tương ứng thay dổi. Ví

dụ:

PHP

<a data-bind="attr: { href: url, title: details }">

Report

</a>

<script type="text/javascript">

var viewModel = {

url: ko.observable("year-end.html"),

details: ko.observable("Report including final year-end statistics")

};

</script>

Ví dụ trên đặt thuộc tính href trên đường dẫn year-end.html và

với title là Report including final year-end statistics.

Phần 2: Control Flow

foreach binding

foreach binding đánh dấu lặp lại số lần tương đương với số phần tử

trong mảng. Nó cũng liên kêts với mỗi sự lặp lại của một mark-up đến

các mục tương ứng của

mảng.

Khởi tạo một viewModel và khởi tạo dữ liệu sẵn như hình dưới

đây:

Kết quả của dữ liệu sẽ pass qua vòng foreach và lấy lần lượt hiển thị

trên browser. Như vậy ta có thể hiểu foreach trong KO về cơ chế cũng

lấy giá trị của object như là foreach giá trị của mảng.

Ngoài ra một số binding rẽ nhánh if, ifnot của KO về cơ bản cấu trúc và

luồng thực thi của nó c cũng như bao câu lệnh rẽ nhánh của các ngôn

ngữ khác.

Phần 3: Tài liệu tham khảo

visible binding

text binding

html binding

css binding

style bindind

attr binding

foreach binding