2.Knockout.Js(監控屬性Observables)


前言

1.創建一個ViewModel

復制代碼
<script type="text/javascript"> //1.創建一個ViewModel var myViewModel = { personName:'aehyok', personAge:25 }; </script> 
復制代碼

2.為ViewModel創建一個聲明式綁定的簡單的View

The name is <span data-bind="text:personName"></span>

3.激活Knockout

1
ko.applyBindings(myViewModel);

4.查看運行效果

Observables監控屬性

  現在已經知道如何創建一個簡單的view model並且通過binding顯示它的屬性了。但是KO一個重要的功能是當你的view model改變的時候能自動更新你的界面。當你的view model部分改變的時候KO是如何知道的呢?答案是:你需要將你的model屬性聲明成observable的, 因為它是非常特殊的JavaScript objects,能夠通知訂閱者它的改變以及自動探測到相關的依賴。

例如:將上述的例子修改為

1
2
3
4
var myViewModel = {
     personName: ko.observable( 'aehyok' ),
     personAge: ko.observable(25)
};

你根本不需要修改view – 所有的data-bind語法依然工作,不同的是他能監控到變化,當值改變時,view會自動更新。

 監控屬性的讀操作(read)

1
2
///監控屬性的讀操作(read)
alert(myViewModel.personAge);

監控屬性的寫操作(write)

1
2
///監控屬性的寫操作(write)
myViewModel.personName( "aehyok-Test" );

  

Dependent Observables依賴監控屬性

如果你已經有了監控屬性firstName和lastName,你想顯示全稱怎么辦? 這就需要用到依賴監控屬性了 – 這些函數是一個或多個監控屬性, 如果他們的依賴對象改變,他們會自動跟着改變。

 例如:繼續在上面的ViewModel中添加兩個屬性 firstName和lastName

1
2
3
4
5
6
var myViewModel = {
     personName: ko.observable( 'aehyok' ),
     personAge: ko.observable(25),
     firstName: ko.observable( 'aehyok' ),
     lastName: ko.observable( 'Leo' )
};

並且添加一個依賴監控屬性,來返回姓名的全稱

1
2
3
4
///依賴監控屬性
myViewModel.fullName = ko.dependentObservable(function () {
     return this .firstName() + " " + this .lastName();
}, myViewModel);

並且綁定到View視圖界面上的元素

The fullname is <span data-bind="text: fullName"></span>

不管firstName還是lastName改變,全稱fullName都會自動更新(不管誰改變,執行函數都會調用一次,不管改變成什么,他的值都會更新到UI或者其他依賴監控屬性上)。

優化上面fullname的監控屬性

  

1
2
3
4
var viewModel = {
     firstName: ko.observable( "aehyok" ),
     lastName:ko.observable( "Leo" )
};

對fullName的依賴監控屬性進行調整

1
2
3
4
5
6
7
8
9
10
11
12
13
viewModel.fullName = ko.dependentObservable({
     read:function() {
         return this .firstName() + " " + this .lastName();
     },
     write:function(value) {
         var lastSpacePos = value.lastIndexOf( " " );
         if (lastSpacePos>0) {
             this .firstName(value.substring(0, lastSpacePos));
             this .lastName(value.substring(lastSpacePos + 1));
         }
     },
     owner: viewModel
});

這個例子里,寫操作的callback接受寫入的值,把值分離出來,分別寫入到“firstName”和“lastName”上。 你可以像普通情況一樣將這個view model綁定到DOM元素上,如下:

 

1
2
3
<p>First name: <span data-bind= "text: firstName" ></span></p>
<p>Last name: <span data-bind= "text: lastName" ></span></p>
<h2>Hello, <input data-bind= "value: fullName" />!</h2>

然后運行在文本框上錄入會看到如下效果

上面的view model演示的是通過一個簡單的參數來初始化依賴監控屬性。你可以給下面的屬性傳入任何JavaScript對象:

 1. read — 必選,一個用來執行取得依賴監控屬性當前值的函數。

 2.write — 可選,如果聲明將使你的依賴監控屬性可寫,別的代碼如果這個可寫功能寫入新值,通過自定義邏輯將值再寫入各個基礎的監控屬性上。

 3.owner — 可選,如果聲明,它就是KO調用read或write的callback時用到的this。

Value轉換器

  有時候你可能需要顯示一些不同格式的數據,從基礎的數據轉化成顯示格式。比如,你存儲價格為float類型,但是允許用戶編輯的字段需要支持貨幣單位和小數點。你可以用可寫的依賴監控屬性來實現,然后解析傳入的數據到基本 float類型里:

1
2
3
4
5
6
7
8
9
10
viewModel.formattedPrice=ko.dependentObservable({
     read:function () {
         return "$" + this .price().toFixed(2);
     },
     write:function(value) {
         value = parseFloat(value.replace(/[^\.\d]/g, "" ));
         this .price(isNaN(value) ? 0 : value);
     },
     owner:viewModel
});

然后綁定到textbox上面

1
<p>Enter bid price: <input data-bind= "value: formattedPrice" /></p>

所以,不管用戶什么時候輸入新價格,輸入什么格式,text box里會自動更新為帶有2位小數點和貨幣符號的數值。這樣用戶可以看到你的程序有多聰明,來告訴用戶只能輸入2位小數,否則的話自動刪除多余的位數,當 然也不能輸入負數,因為write的callback函數會自動刪除負號。

過濾並驗證用戶輸入

繼續在上面的ViewModel中添加兩個屬性

1
2
3
4
5
6
7
var viewModel = {
     firstName: ko.observable( "aehyok" ),
     lastName: ko.observable( "Leo" ),
     price: ko.observable(22.466),
     acceptedNumericValue: ko.observable(123),
     lastInputWasValid: ko.observable( true )
};

 然后添加一個依賴監控屬性

1
2
3
4
5
6
7
8
9
10
11
12
viewModel.attemptedValue = ko.dependentObservable({
     read: viewModel.acceptedNumericValue,
     write: function (value) {
         if (isNaN(value)) {
             this .lastInputWasValid( false );
         } else {
             this .lastInputWasValid( true );
             this .acceptedNumericValue(value);
         }
     },
     owner:viewModel
});

進行綁定View視圖界面元素

1
2
<p>Enter a numeric value: <input data-bind= "value: attemptedValue" /></p>
<div data-bind= "visible: !lastInputWasValid()" >That's not a number!</div>

現在,acceptedNumericValue 將只接受數字,其它任何輸入的值都會觸發顯示驗證信息,而會更新acceptedNumericValue。

前言

  如果你要探測和響應一個對象的變化,你應該用observables。

  如果你需要探測和響應一個集合對象的變化,你應該用observableArray 。

  在很多場景下,它都非常有用,比如你要在UI上需要顯示/編輯的一個列表數據集合,然后對集合進行添加和刪除。

使用observables數組

 1.簡單舉例

<script type="text/javascript"> var myObservableArray = ko.observableArray(); ///初始化一個空的數組 myObservableArray.push("Some Value"); ///向數組中添加一個項 </script>

2.關鍵點:監控數組跟蹤的是數組里的對象,而不是這些對象自身的狀態。

簡單說,將一對象放在observableArray 里不會使這個對象本身的屬性變化可監控的。當然你自己也可以聲明這個對象的屬性為observable的,但它就成了一個依賴監控對象了。一個 observableArray 僅僅監控他擁有的對象,並在這些對象添加或者刪除的時候發出通知。

3.預加載一個監控數組observableArray

如果你想讓你的監控數組在開始的時候就有一些初始值,那么在聲明的時候,你可以在構造器里加入這些初始對象。例如:

    var anotherObservableArray = ko.observableArray([ { name: "Bungle", type: "Bear" }, { name: "George", type: "Hippo" }, { name: "Zippy", type: "Unknown" } ]);

4.從observableArray里讀取信息

一個observableArray其實就是一個observable的監控對象,只不過他的值是一個數組(observableArray還加了 很多其他特性,稍后介紹)。所以你可以像獲取普通的observable的值一樣,只需要調用無參函數就可以獲取自身的值了。 例如,你可以像下面這樣獲取它的值:

    alert('The length of the array is ' + myObservableArray().length); alert('The first element is ' + myObservableArray()[0]);

理論上你可以使用任何原生的JavaScript數組函數來操作這些數組,但是KO提供了更好的功能等價函數,他們非常有用是因為:

  A:兼容所有瀏覽器。(例如indexOf不能在IE8和早期版本上使用,但KO自己的indexOf 可以在所有瀏覽器上使用)

  B:在數組操作函數方面(例如push和splice),KO自己的方式可以自動觸發依賴跟蹤,並且通知所有的訂閱者它的變化,然后讓UI界面也相應的自動更新。

  C:語法更方便,調用KO的push方法,只需要這樣寫:myObservableArray.push(...)。 比如原生數組的myObservableArray().push(...)好用多了。

5.IndexOf和slice

  indexOf 函數返回的是第一個等於你參數數組項的索引。例如:myObservableArray.indexOf('Blah')將返回以0為第一個索引的第一個等於Blah的數組項的索引。如果沒有找到相等的,將返回-1。  

  slice函數是observableArray相對於JavaScript 原生函數slice的等價函數(返回給定的從開始索引到結束索引之間所有的對象集合)。 調用myObservableArray.slice(...)等價於調用JavaScript原生函數(例 如:myObservableArray().slice(...))。

6.操作observableArray

  observableArray 展現的是數組對象相似的函數並通知訂閱者的功能。

pop, push, shift, unshift, reverse, sort, splice

所有這些函數都是和JavaScript數組原生函數等價的,唯一不同的數組改變可以通知訂閱者:

復制代碼
    myObservableArray.push('Some new value');// 在數組末尾添加一個新項  myObservableArray.pop();// 刪除數組最后一個項並返回該項  myObservableArray.unshift('Some new value');// 在數組頭部添加一個項  myObservableArray.shift();// 刪除數組頭部第一項並返回該項  myObservableArray.reverse();// 翻轉整個數組的順序  myObservableArray.sort();// 給數組排序
復制代碼

默認情況下,是按照字符排序(如果是字符)或者數字排序(如果是數字)。

   你可以排序傳入一個排序函數進行排序,該排序函數需要接受2個參數(代表該數組里需要比較的項),如果第一個項小於第二個項,返回-1,大於則返回1,等於返回0。例如:用lastname給person排序,你可以這樣寫:

    myObservableArray.sort(
        function(left, right) { return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1); });

myObservableArray.splice() 刪除指定開始索引和指定數目的數組對象元素。例如myObservableArray.splice(1, 3) 從索引1開始刪除3個元素(第2,3,4個元素)然后將這些元素作為一個數組對象返回。

更多observableArray 函數的信息,請參考等價的JavaScript數組標准函數

7.remove和removeAll

observableArray 添加了一些JavaScript數組默認沒有但非常有用的函數:

    myObservableArray.remove(someItem);// 刪除所有等於someItem的元素並將被刪除元素作為一個數組返回  myObservableArray.remove(function (item) { return item.age < 18;}) ;//刪除所有age屬性小於18的元素並將被刪除元素作為一個數組返回  myObservableArray.removeAll(['Chad', 132, undefined]);//刪除所有等於'Chad', 123, or undefined的元素並將被刪除元素作為一個數組返回


免責聲明!

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



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