2.Knockout.Js(监控属性Observables)
前言
1.創(chuàng)建一個(gè)ViewModel
<script type="text/javascript">//1.創(chuàng)建一個(gè)ViewModelvar myViewModel = { personName:'aehyok', personAge:25 }; </script>2.為ViewModel創(chuàng)建一個(gè)聲明式綁定的簡(jiǎn)單的View
The name is <span data-bind="text:personName"></span>3.激活Knockout
| 1 | ko.applyBindings(myViewModel); |
4.查看運(yùn)行效果
Observables監(jiān)控屬性
現(xiàn)在已經(jīng)知道如何創(chuàng)建一個(gè)簡(jiǎn)單的view model并且通過binding顯示它的屬性了。但是KO一個(gè)重要的功能是當(dāng)你的view model改變的時(shí)候能自動(dòng)更新你的界面。當(dāng)你的view model部分改變的時(shí)候KO是如何知道的呢?答案是:你需要將你的model屬性聲明成observable的, 因?yàn)樗欠浅L厥獾腏avaScript objects,能夠通知訂閱者它的改變以及自動(dòng)探測(cè)到相關(guān)的依賴。
例如:將上述的例子修改為
| 1 2 3 4 | var myViewModel = { ????personName: ko.observable('aehyok'), ????personAge: ko.observable(25) }; |
你根本不需要修改view – 所有的data-bind語法依然工作,不同的是他能監(jiān)控到變化,當(dāng)值改變時(shí),view會(huì)自動(dòng)更新。
?監(jiān)控屬性的讀操作(read)
| 1 2 | ///監(jiān)控屬性的讀操作(read) alert(myViewModel.personAge); |
監(jiān)控屬性的寫操作(write)
| 1 2 | ///監(jiān)控屬性的寫操作(write) myViewModel.personName("aehyok-Test"); |
Dependent Observables依賴監(jiān)控屬性
如果你已經(jīng)有了監(jiān)控屬性firstName和lastName,你想顯示全稱怎么辦? 這就需要用到依賴監(jiān)控屬性了 – 這些函數(shù)是一個(gè)或多個(gè)監(jiān)控屬性, 如果他們的依賴對(duì)象改變,他們會(huì)自動(dòng)跟著改變。
?例如:繼續(xù)在上面的ViewModel中添加兩個(gè)屬性 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') }; |
并且添加一個(gè)依賴監(jiān)控屬性,來返回姓名的全稱
| 1 2 3 4 | ///依賴監(jiān)控屬性 myViewModel.fullName = ko.dependentObservable(function () { ????return this.firstName() + " " + this.lastName(); }, myViewModel); |
并且綁定到View視圖界面上的元素
The fullname is <span data-bind="text: fullName"></span>不管firstName還是lastName改變,全稱fullName都會(huì)自動(dòng)更新(不管誰改變,執(zhí)行函數(shù)都會(huì)調(diào)用一次,不管改變成什么,他的值都會(huì)更新到UI或者其他依賴監(jiān)控屬性上)。
優(yōu)化上面fullname的監(jiān)控屬性
| 1 2 3 4 | var viewModel = { ????firstName: ko.observable("aehyok"), ????lastName:ko.observable("Leo") }; |
對(duì)fullName的依賴監(jiān)控屬性進(jìn)行調(diào)整
| 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 }); |
這個(gè)例子里,寫操作的callback接受寫入的值,把值分離出來,分別寫入到“firstName”和“l(fā)astName”上。 你可以像普通情況一樣將這個(gè)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> |
然后運(yùn)行在文本框上錄入會(huì)看到如下效果
上面的view model演示的是通過一個(gè)簡(jiǎn)單的參數(shù)來初始化依賴監(jiān)控屬性。你可以給下面的屬性傳入任何JavaScript對(duì)象:
?1.?read — 必選,一個(gè)用來執(zhí)行取得依賴監(jiān)控屬性當(dāng)前值的函數(shù)。
?2.write — 可選,如果聲明將使你的依賴監(jiān)控屬性可寫,別的代碼如果這個(gè)可寫功能寫入新值,通過自定義邏輯將值再寫入各個(gè)基礎(chǔ)的監(jiān)控屬性上。
?3.owner — 可選,如果聲明,它就是KO調(diào)用read或write的callback時(shí)用到的this。
Value轉(zhuǎn)換器
有時(shí)候你可能需要顯示一些不同格式的數(shù)據(jù),從基礎(chǔ)的數(shù)據(jù)轉(zhuǎn)化成顯示格式。比如,你存儲(chǔ)價(jià)格為float類型,但是允許用戶編輯的字段需要支持貨幣單位和小數(shù)點(diǎn)。你可以用可寫的依賴監(jiān)控屬性來實(shí)現(xiàn),然后解析傳入的數(shù)據(jù)到基本 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> |
所以,不管用戶什么時(shí)候輸入新價(jià)格,輸入什么格式,text box里會(huì)自動(dòng)更新為帶有2位小數(shù)點(diǎn)和貨幣符號(hào)的數(shù)值。這樣用戶可以看到你的程序有多聰明,來告訴用戶只能輸入2位小數(shù),否則的話自動(dòng)刪除多余的位數(shù),當(dāng) 然也不能輸入負(fù)數(shù),因?yàn)閣rite的callback函數(shù)會(huì)自動(dòng)刪除負(fù)號(hào)。
過濾并驗(yàn)證用戶輸入
繼續(xù)在上面的ViewModel中添加兩個(gè)屬性
| 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) }; |
?然后添加一個(gè)依賴監(jiān)控屬性
| 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 }); |
進(jìn)行綁定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> |
現(xiàn)在,acceptedNumericValue 將只接受數(shù)字,其它任何輸入的值都會(huì)觸發(fā)顯示驗(yàn)證信息,而會(huì)更新acceptedNumericValue。
前言
如果你要探測(cè)和響應(yīng)一個(gè)對(duì)象的變化,你應(yīng)該用observables。
如果你需要探測(cè)和響應(yīng)一個(gè)集合對(duì)象的變化,你應(yīng)該用observableArray 。
在很多場(chǎng)景下,它都非常有用,比如你要在UI上需要顯示/編輯的一個(gè)列表數(shù)據(jù)集合,然后對(duì)集合進(jìn)行添加和刪除。
使用observables數(shù)組
?1.簡(jiǎn)單舉例
<script type="text/javascript">var myObservableArray = ko.observableArray(); ///初始化一個(gè)空的數(shù)組 myObservableArray.push("Some Value"); ///向數(shù)組中添加一個(gè)項(xiàng) </script>2.關(guān)鍵點(diǎn):監(jiān)控?cái)?shù)組跟蹤的是數(shù)組里的對(duì)象,而不是這些對(duì)象自身的狀態(tài)。
簡(jiǎn)單說,將一對(duì)象放在observableArray 里不會(huì)使這個(gè)對(duì)象本身的屬性變化可監(jiān)控的。當(dāng)然你自己也可以聲明這個(gè)對(duì)象的屬性為observable的,但它就成了一個(gè)依賴監(jiān)控對(duì)象了。一個(gè) observableArray 僅僅監(jiān)控他擁有的對(duì)象,并在這些對(duì)象添加或者刪除的時(shí)候發(fā)出通知。
3.預(yù)加載一個(gè)監(jiān)控?cái)?shù)組observableArray
如果你想讓你的監(jiān)控?cái)?shù)組在開始的時(shí)候就有一些初始值,那么在聲明的時(shí)候,你可以在構(gòu)造器里加入這些初始對(duì)象。例如:
var anotherObservableArray = ko.observableArray([{ name: "Bungle", type: "Bear" }, { name: "George", type: "Hippo" }, { name: "Zippy", type: "Unknown" } ]);4.從observableArray里讀取信息
一個(gè)observableArray其實(shí)就是一個(gè)observable的監(jiān)控對(duì)象,只不過他的值是一個(gè)數(shù)組(observableArray還加了 很多其他特性,稍后介紹)。所以你可以像獲取普通的observable的值一樣,只需要調(diào)用無參函數(shù)就可以獲取自身的值了。 例如,你可以像下面這樣獲取它的值:
alert('The length of the array is ' + myObservableArray().length);alert('The first element is ' + myObservableArray()[0]);理論上你可以使用任何原生的JavaScript數(shù)組函數(shù)來操作這些數(shù)組,但是KO提供了更好的功能等價(jià)函數(shù),他們非常有用是因?yàn)?#xff1a;
A:兼容所有瀏覽器。(例如indexOf不能在IE8和早期版本上使用,但KO自己的indexOf 可以在所有瀏覽器上使用)
B:在數(shù)組操作函數(shù)方面(例如push和splice),KO自己的方式可以自動(dòng)觸發(fā)依賴跟蹤,并且通知所有的訂閱者它的變化,然后讓UI界面也相應(yīng)的自動(dòng)更新。
C:語法更方便,調(diào)用KO的push方法,只需要這樣寫:myObservableArray.push(...)。 比如原生數(shù)組的myObservableArray().push(...)好用多了。
5.IndexOf和slice
indexOf 函數(shù)返回的是第一個(gè)等于你參數(shù)數(shù)組項(xiàng)的索引。例如:myObservableArray.indexOf('Blah')將返回以0為第一個(gè)索引的第一個(gè)等于Blah的數(shù)組項(xiàng)的索引。如果沒有找到相等的,將返回-1。
slice函數(shù)是observableArray相對(duì)于JavaScript 原生函數(shù)slice的等價(jià)函數(shù)(返回給定的從開始索引到結(jié)束索引之間所有的對(duì)象集合)。 調(diào)用myObservableArray.slice(...)等價(jià)于調(diào)用JavaScript原生函數(shù)(例 如:myObservableArray().slice(...))。
6.操作observableArray
observableArray 展現(xiàn)的是數(shù)組對(duì)象相似的函數(shù)并通知訂閱者的功能。
pop, push, shift, unshift, reverse, sort, splice
所有這些函數(shù)都是和JavaScript數(shù)組原生函數(shù)等價(jià)的,唯一不同的數(shù)組改變可以通知訂閱者:
myObservableArray.push('Some new value');// 在數(shù)組末尾添加一個(gè)新項(xiàng) myObservableArray.pop();// 刪除數(shù)組最后一個(gè)項(xiàng)并返回該項(xiàng) myObservableArray.unshift('Some new value');// 在數(shù)組頭部添加一個(gè)項(xiàng) myObservableArray.shift();// 刪除數(shù)組頭部第一項(xiàng)并返回該項(xiàng) myObservableArray.reverse();// 翻轉(zhuǎn)整個(gè)數(shù)組的順序 myObservableArray.sort();// 給數(shù)組排序默認(rèn)情況下,是按照字符排序(如果是字符)或者數(shù)字排序(如果是數(shù)字)。
?? 你可以排序傳入一個(gè)排序函數(shù)進(jìn)行排序,該排序函數(shù)需要接受2個(gè)參數(shù)(代表該數(shù)組里需要比較的項(xiàng)),如果第一個(gè)項(xiàng)小于第二個(gè)項(xiàng),返回-1,大于則返回1,等于返回0。例如:用lastname給person排序,你可以這樣寫:
myObservableArray.sort(function(left, right) {return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1);});myObservableArray.splice() 刪除指定開始索引和指定數(shù)目的數(shù)組對(duì)象元素。例如myObservableArray.splice(1, 3) 從索引1開始刪除3個(gè)元素(第2,3,4個(gè)元素)然后將這些元素作為一個(gè)數(shù)組對(duì)象返回。
更多observableArray 函數(shù)的信息,請(qǐng)參考等價(jià)的JavaScript數(shù)組標(biāo)準(zhǔn)函數(shù)。
7.remove和removeAll
observableArray 添加了一些JavaScript數(shù)組默認(rèn)沒有但非常有用的函數(shù):
myObservableArray.remove(someItem);// 刪除所有等于someItem的元素并將被刪除元素作為一個(gè)數(shù)組返回 myObservableArray.remove(function (item) { return item.age < 18;}) ;//刪除所有age屬性小于18的元素并將被刪除元素作為一個(gè)數(shù)組返回 myObservableArray.removeAll(['Chad', 132, undefined]);//刪除所有等于'Chad', 123, or undefined的元素并將被刪除元素作為一個(gè)數(shù)組返回轉(zhuǎn)載于:https://www.cnblogs.com/TF12138/p/4156888.html
總結(jié)
以上是生活随笔為你收集整理的2.Knockout.Js(监控属性Observables)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 陶陶的兔二,建好啦!
- 下一篇: cobbler自动化安装详解