Javascript MVVM模式前端框架—Knockout 2.1.0系列(1):初識Ko,了解Observable與computed


*本文已經同步至索引目錄:http://www.cnblogs.com/wbpmrck/archive/2012/05/16/Knockout-introduction.html

KO是什么?

KO不是萬能的,它的出現主要是為了方便的解決下面的問題:

  • UI元素較多,用戶交互比較頻繁,需要編寫大量的手工代碼維護UI元素的狀態、樣式等屬性?
  • UI元素之間關系比較緊密,比如操作一個元素,需要改變另外一個元素的狀態?
  • DOM元素與Js對象之間的數據同步?
  • 前端javascript代碼組織不理想?用戶輸入數據校驗、DOM操作、后台交互…,交織在一起?

基礎概念一:viewModel

  • 負責處理UI事件的響應,響應用戶操作。
  • 負責保存領域模型在前端的變體Model’,比如:Student模型,在UI元素與Model之間同步數據(用戶修改input-->ko修改model,反之亦然)
  • 在需要的時候,可以使用Helper方法輕松地從viewModel中剝離出需要傳遞給Server的數據,通過ajax方式與后台交互。
  • 負責接收Server端發送過來的數據(可能是Ajax請求),更新模型數據,同時更新UI展現。

基礎概念二:Observable與computed

縱觀KO的所有應用場景,基本上這2個屬性至少會用到一個。個人認為這是KO最常使用的東西。他們用法如下:

  • Observable(監控屬性):監控自身屬性的變化,向外部發送通知。外部通過subscribe方法來訂閱屬性的變化事件。
  • Computed(依賴屬性):在早期版本中叫做dependentObservable,它通常依賴於其他的Observable,通過計算得出自己的數據。當依賴項改變的時候,computed屬性會接到通知,然后同步更新自身

*這里提2點:

  • 雖然本文稱之為“屬性”,但是本質上他們是js的function對象,所以訪問的時候需要加()號
  • 默認情況下Computed的同步發生在任意的Observable變化的時候,可是某些情況下我們可能不希望它更新的如此頻繁,比如用戶正在輸入的過程中。KO有其他辦法來延遲更新,在本系列后面會有專門文章介紹。

本章的重點就是講解這2個基本屬性的用法,在后面的“實例講解”中會詳細說明。

如何激活KO綁定

KO中,綁定是需要激活的,可以理解為把viewModel的數據與Html文檔的DOM元素進行分析和關聯

通常是在頁面元素、viewModel數據加載完畢之后,就可以激活綁定了。當然你可以在任何時候你想進行綁定的時候來激活。

只需要下面的代碼:

 var model = new AppViewModel();//實例化一個viewModel
 ko.applyBindings(model); //綁定到整個頁面

這樣KO會在整個Body中尋找需要進行綁定的元素,與viewModel進行綁定。當然你也可以指定綁定的根節點,這樣的好處:

  1. 可以縮小KO查找綁定的范圍(畢竟不是整個頁面都需要進行binding)
  2. 可以同時使用多個viewModel,分別負責不同區域的綁定(是不是你想要的?haha…)

很簡單,加一個參數即可:

var model = new AppViewModel();
ko.applyBindings(model, document.getElementById("Demo1")); //Demo1可能是一個Div

 

實例講解:Observable

基本語法

1、定義

var myViewModel = {
    personName: ko.observable('Bob'),//定義叫做personName的監控屬性
    personAge: ko.observable(123)//定義叫做personAge的監控屬性
};

2、讀取

var a=myViewModel.personName();//a為'Bob'

3、寫入、連續寫入(鏈式調用)

myViewModel.personName('Mary').personAge(50);//同時修改了2個屬性值

 4、訂閱屬性修改事件

myViewModel.personName.subscribe(function(newValue) {
    alert("The person's new name is " + newValue);
});

myViewModel.personName('換個名字');//這時候會彈出alert

Demo

http://jsfiddle.net/wbpmrck/LkTxp/69/embedded/

看不到內嵌Demo的點這里查看在線Demo

(如果大家可以看到內嵌Demo,直接點擊Result或者向右小三角看結果)

 ps:

  1. 折騰了半天才繞過了博客園對iframe的過濾,如果個別童鞋看不到demo,請點擊上面的鏈接看demo~
  2. demo中為了演示功能,提前使用了后面會說到的click綁定,原因是我發現jsFiddle網站上用onclick綁定本地js函數無法訪問。如果有哪位知道的麻煩告知一下,謝謝!
  3. 大家只需關注點擊處理函數中如何讀取和修改observable的部分即可

實例講解:Computed

在上面例子中,我們有2個屬性firstName和lastName,但是如果我們想顯示一個全名,並且希望這個全名可以根據firstName和lastName的變化而變化,怎么辦?下面Computed登場!

基本語法

1、定義Computed屬性

function AppViewModel() {
    var self = this;
 
    self.firstName = ko.observable('Bob');
    self.lastName = ko.observable('Smith');     
   //下面這個屬性依賴上面的2個屬性存在
    self.fullName = ko.computed(function() {
        return self.firstName() + " " + self.lastName();
    });
}

2、讀取Computed屬性

var model = new AppViewModel();
var full =model.fullName();//full="Bob Smith"

Demo

http://jsfiddle.net/wbpmrck/hb8HD/14/embedded/

 看不到內嵌Demo的點這里查看在線Demo

說明:

為了演示方便,這里提前使用了text綁定和value綁定來顯示viewModel屬性的值,這個綁定很好理解,后面會說到

到這里,大家可能已經感覺到computed比較特殊,他是動態計算的,那么如果要“修改”computed怎么做?看下面。

高級語法

1、可‘寫’的Computed

this.fullName = ko.computed({
        //調用fullName()讀取時,會執行這里
        read: function () {
            return this.firstName() + " " + this.lastName(); 
        },
        //調用fullName('xx')寫入時,會執行這里
        write: function (value) {
            var lastSpacePos = value.lastIndexOf(" ");
            if (lastSpacePos > 0) { // Ignore values with no space character
                this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
                this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
            }
        },
        //傳入一個對象,該對象作為this指針在read,write方法中使用
        owner: this
    });

語法說明:

  1. read屬性:自定義函數,該函數的返回值就是調用fullName()獲取computed屬性值時得到的結果
  2. write屬性:自定義函數,該函數通過修改依賴項firstName和lastName來修改自身
  3. owner屬性:傳入對象,該對象作為this關鍵字在read和write方法中使用(函數的調用對象,不明白的童鞋回去看看js基礎...)

Demo

http://jsfiddle.net/wbpmrck/hb8HD/21/embedded/

 看不到內嵌Demo的點這里查看在線Demo

總結

本文主要介紹了ko中的observable和computed用法,它們是ko的核心組件,也是實現依賴跟蹤的關鍵點。

感謝支持

如果本文對您有幫助的話,請別吝嗇手中的推薦票哦~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM