精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Knockout應(yīng)用開發(fā)指南之監(jiān)控屬性(Observables)

開發(fā) 前端
Knockout使用js代碼達(dá)到雙向綁定的目的,類似Silverlight/WPF里的綁定一樣,我們主要就是利用相關(guān)的特性進(jìn)行開發(fā)的,極大地減少了代碼開發(fā)量。

關(guān)于Knockout的3個(gè)重要概念(Observables,DependentObservables,ObservableArray),本人無(wú)法準(zhǔn)確表達(dá)它的準(zhǔn)確含義,所以暫定翻譯為(監(jiān)控屬性、依賴監(jiān)控屬性和監(jiān)控?cái)?shù)組),如果有好的建議請(qǐng)指正,多謝。

1 創(chuàng)建帶有監(jiān)控屬性的view model

Observables

Knockout是在下面三個(gè)核心功能是建立起來(lái)的:

◆ 監(jiān)控屬性(Observables)和依賴跟蹤(Dependency tracking)

◆ 聲明式綁定(Declarative bindings)

◆ 模板(Templating)

這一節(jié),你講學(xué)到3個(gè)功能中的***個(gè)。 在這之前, 我們來(lái)解釋一下MVVM模式和view model的概念。

MVVM and View Models

Model-View-View Model (MVVM) 是一種創(chuàng)建用戶界面的設(shè)計(jì)模式。 描述的是如何將復(fù)雜的UI用戶界面分成3個(gè)部分:

◆ model: 你程序里存儲(chǔ)的數(shù)據(jù)。這個(gè)數(shù)據(jù)包括對(duì)象和業(yè)務(wù)操作(例如:銀子賬戶可以完成轉(zhuǎn)賬功能), 并且獨(dú)立于任何UI。使用KO的時(shí)候,通常說(shuō)是向服務(wù)器調(diào)用Ajax讀寫這個(gè)存儲(chǔ)的模型數(shù)據(jù)。

◆ view model: 在UI上,純code描述的數(shù)據(jù)以及操作。例如,如果你實(shí)現(xiàn)列表編輯,你的view model應(yīng)該是一個(gè)包含列表項(xiàng)items的對(duì)象和暴露的add/remove列表項(xiàng)(item)的操作方法。

注意這不是UI本身:它不包含任何按鈕的概念或者顯示風(fēng)格。它也不是持續(xù)數(shù)據(jù)模型 – 包含用戶正在使用的未保存數(shù)據(jù)。使用KO的時(shí)候,你的view models是不包含任何HTML知識(shí)的純JavaScript 對(duì)象。保持view model抽象可以保持簡(jiǎn)單,以便你能管理更復(fù)雜的行為。

◆ view: 一個(gè)可見的,交互式的,表示view model狀態(tài)的UI。 從view model顯示數(shù)據(jù),發(fā)送命令到view model(例如:當(dāng)用戶click按鈕的時(shí)候) ,任何view model狀態(tài)改變的時(shí)候更新。

使用KO的時(shí)候,你的view就是你帶有綁定信息的HTML文檔,這些聲明式的綁定管理到你的view model上。或者你可以使用模板從你的view model獲取數(shù)據(jù)生成HTML。

創(chuàng)建一個(gè)view model,只需要聲明任意的JavaScript object。例如:

  1. var myViewModel = {  
  2.     personName: 'Bob',  
  3.     personAge: 123  
  4. }; 

你可以為view model創(chuàng)建一個(gè)聲明式綁定的簡(jiǎn)單view。例如:下面的代碼顯示personName 值:

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

Activating Knockout

data-bind屬性盡快好用但它不是HTML的原生屬性(它嚴(yán)格遵從HTML5語(yǔ)法, 雖然HTML4驗(yàn)證器提示有不可識(shí)別的屬性但依然可用)。由于瀏覽器不識(shí)別它是什么意思,所以你需要激活Knockout 來(lái)讓他起作用。

激活Knockout,需要添加如下的 <script> 代碼塊:

  1. ko.applyBindings(myViewModel); 

你可以將這個(gè)代碼塊放在HTML底部,或者放在jQuery的$函數(shù)或者ready 函數(shù)里,然后放在頁(yè)面上面, 最終生成結(jié)果就是如下的HTML代碼:

  1. The name is <span>Bob</span> 

你可能奇怪ko.applyBindings使用的是什么樣的參數(shù),

◆ ***個(gè)參數(shù)是你想用于聲明式綁定

◆ 第二個(gè)參數(shù)(可選),可以聲明成使用data-bind的HTML元素或者容器。例如, ko.applyBindings(myViewModel, document.getElementById('someElementId'))。它的現(xiàn)在是只有作為someElementId 的元素和子元素才能激活KO功能。 好處是你可以在同一個(gè)頁(yè)面聲明多個(gè)view model,用來(lái)區(qū)分區(qū)域。

Observables

現(xiàn)在已經(jīng)知道如何創(chuàng)建一個(gè)簡(jiǎn)單的view model并且通過(guò)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)的依賴。

例如:將上述例子的view model改成如下代碼:

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

你根本不需要修改view – 所有的data-bind語(yǔ)法依然工作,不同的是他能監(jiān)控到變化,當(dāng)值改變時(shí),view會(huì)自動(dòng)更新。

監(jiān)控屬性(observables)的讀和寫

不是所有的瀏覽器都支持JavaScript的 getters and setters (比如IE),,所以為了兼容性,使用ko.observable監(jiān)控的對(duì)象都是真實(shí)的function函數(shù)。

◆  讀取監(jiān)控屬性(observable)的值,只需要直接調(diào)用監(jiān)控屬性(observable)(不需要參數(shù)),例如myViewModel.personName() 將返回'Bob', myViewModel.personAge() 將返回 123。

◆  寫一個(gè)新值到監(jiān)控屬性(observable)上,調(diào)用這個(gè)observable屬性并當(dāng)新值作為參數(shù)。例如:調(diào)用 myViewModel.personName('Mary') 將更新name值為'Mary'。

◆  給一個(gè)model對(duì)象的多個(gè)屬性寫入新值,你可以使用鏈?zhǔn)秸Z(yǔ)法。例如: myViewModel.personName('Mary').personAge(50) 將會(huì)將name更新為 'Mary' 并且 將age更新為 50.

監(jiān)控屬性(observables)的特征就是監(jiān)控(observed),例如其它代碼可以說(shuō)我需要得到對(duì)象變化的通知,所以KO內(nèi)部有很多內(nèi)置的綁定語(yǔ)法。所以如果你的代碼寫成data-bind="text: personName", text綁定注冊(cè)到自身,一旦personName的值改變,它就能得到通知。

當(dāng)然調(diào)用myViewModel.personName('Mary')改變name的值,text綁定將自動(dòng)更新這個(gè)新值到相應(yīng)的DOM元素上。這就是如何將view model的改變傳播到view上的。

監(jiān)控屬性(Observables)的顯式訂閱

通常情況下,你不用手工訂閱,所以新手可以忽略此小節(jié)。高級(jí)用戶,如果你要注冊(cè)自己的訂閱到監(jiān)控屬性(observables),你可以調(diào)用它的subscribe 函數(shù)。例如:

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

這個(gè)subscribe 函數(shù)在內(nèi)部很多地方都用到的。你也可以終止自己的訂閱:首先得到你的訂閱,然后調(diào)用這個(gè)對(duì)象的dispose函數(shù),例如:

  1. var subscription = myViewModel.personName.subscribe(function (newValue) { /* do stuff */ });  
  2. // ...then later...  
  3. subscription.dispose(); // I no longer want notifications 

大多數(shù)情況下,你不需要做這些,因?yàn)閮?nèi)置的綁定和模板系統(tǒng)已經(jīng)幫你做好很多事情了,可以直接使用它們。

2 使用依賴監(jiān)控屬性(Dependent Observables)

如果你已經(jīng)有了監(jiān)控屬性firstName和lastName,你想顯示全稱怎么辦? 這就需要用到依賴監(jiān)控屬性了 – 這些函數(shù)是一個(gè)或多個(gè)監(jiān)控屬性, 如果他們的依賴對(duì)象改變,他們會(huì)自動(dòng)跟著改變。

例如,下面的view model,

  1. var viewModel = {  
  2.     firstName: ko.observable('Bob'),  
  3.     lastName: ko.observable('Smith')  
  4. }; 

… 你可以添加一個(gè)依賴監(jiān)控屬性來(lái)返回姓名全稱:

  1. viewModel.fullName = ko.dependentObservable(function () {  
  2.     return this.firstName() + " " + this.lastName();  
  3. }, viewModel); 

并且綁定到UI的元素上,例如:

  1. The name is <span data-bind="text: fullName"></span> 

… 不管firstName還是lastName改變,全稱fullName都會(huì)自動(dòng)更新(不管誰(shuí)改變,執(zhí)行函數(shù)都會(huì)調(diào)用一次,不管改變成什么,他的值都會(huì)更新到UI或者其他依賴監(jiān)控屬性上)。

管理‘this’

新手可忽略此小節(jié),你只需要安裝上面例子中的代碼模式寫就行了,無(wú)需知道/關(guān)注這個(gè)this。

你可能疑惑ko.dependentObservable的第二個(gè)參數(shù)是做什么用的(上面的例子中我傳的是viewModel), 它是聲明執(zhí)行依賴監(jiān)控屬性的this用的。 沒(méi)有它,你不能引用到this.firstName() 和this.lastName()。 老練的JavaScript 開發(fā)人員不覺(jué)得this怎么樣,但是如果你不熟悉JavaScript,那就對(duì)它就會(huì)很陌生。(C#和Java需要不需要為set一個(gè)值為設(shè)置this,但是JavaScript 需要,因?yàn)槟J(rèn)情況下他們的函數(shù)自身不是任何對(duì)象的一部分)。

不幸的是, JavaScript 對(duì)象沒(méi)有任何辦法能引用他們自身,所以你需要通過(guò)myViewModelObject.myDependentObservable = ... 的形式添加依賴監(jiān)控屬性到view model對(duì)象上。 你不能直接在view model里聲明他們,換句話說(shuō),你不能寫成下面這樣:

  1. var viewModel = {  
  2.     myDependentObservable: ko.dependentObservable(function() {  
  3.         ...  
  4.     }, /* can't refer to viewModel from here, so this doesn't work */)  

… 相反你必須寫成如下這樣:

  1. var viewModel = {  
  2.     // Add other properties here as you wish  
  3. };  
  4.  
  5. viewModel.myDependentObservable = ko.dependentObservable(function() {  
  6.     ...  
  7. }, viewModel); // This is OK 

只要你知道期望什么,它確實(shí)不是個(gè)問(wèn)題。

依賴鏈

理所當(dāng)然,如果你想你可以創(chuàng)建一個(gè)依賴監(jiān)控屬性的鏈。例如:

◆ 監(jiān)控屬性items表述一組列表項(xiàng)

◆ 監(jiān)控屬性selectedIndexes保存著被用戶選上的列表項(xiàng)的索引

◆ 依賴監(jiān)控屬性selectedItems 返回的是selectedIndexes 對(duì)應(yīng)的列表項(xiàng)數(shù)組

◆ 另一個(gè)依賴監(jiān)控屬性返回的true或false依賴于 selectedItems 的各個(gè)列表項(xiàng)是否包含一些屬性(例如,是否新的或者還未保存的)。一些UI element(像按鈕的啟用/禁用)的狀態(tài)取決于這個(gè)值)。

然后,items或者selectedIndexes 的改變將會(huì)影響到所有依賴監(jiān)控屬性的鏈,所有綁定這些屬性的UI元素都會(huì)自動(dòng)更新。多么整齊與優(yōu)雅!

可寫的依賴監(jiān)控屬性

新手可忽略此小節(jié),可寫依賴監(jiān)控屬性真的是太advanced了,而且大部分情況下都用不到。

正如所學(xué)到的,依賴監(jiān)控屬性是通過(guò)計(jì)算其它的監(jiān)控屬性而得到的。感覺(jué)是依賴監(jiān)控屬性正常情況下應(yīng)該是只讀的。那么,有可能讓依賴監(jiān)控屬性支持可寫么?你只需要聲明自己的callback函數(shù)然后利用寫入的值再處理一下相應(yīng)的邏輯即可。

你可以像使用普通的監(jiān)控屬性一樣使用依賴監(jiān)控屬性 – 數(shù)據(jù)雙向綁定到DOM元素上,并且通過(guò)自定義的邏輯攔截所有的讀和寫操作。這是非常牛逼的特性并且可以在大范圍內(nèi)使用。

例1:分解用戶的輸入

返回到經(jīng)典的“first name + last name = full name” 例子上,你可以讓事情調(diào)回來(lái)看: 讓依賴監(jiān)控屬性fullName可寫,讓用戶直接輸入姓名全稱,然后輸入的值將被解析并映射寫入到基本的監(jiān)控屬性firstName和lastName上:

  1. var viewModel = {  
  2.     firstName: ko.observable("Planet"),  
  3.     lastName: ko.observable("Earth")  
  4. };  
  5.  
  6. viewModel.fullName = ko.dependentObservable({  
  7.  
  8.     read: function () {  
  9.         return this.firstName() + " " + this.lastName();  
  10.     },  
  11.  
  12.     write: function (value) {  
  13.         var lastSpacePos = value.lastIndexOf(" ");  
  14.         if (lastSpacePos > 0) { // Ignore values with no space character  
  15.             this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"  
  16.             this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"  
  17.         }  
  18.     },  
  19.     owner: viewModel  
  20. }); 

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

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

這是一個(gè)Hello World 例子的反例子,姓和名都不可編輯,相反姓和名組成的姓名全稱卻是可編輯的。

上面的view model演示的是通過(guò)一個(gè)簡(jiǎn)單的參數(shù)來(lái)初始化依賴監(jiān)控屬性。你可以給下面的屬性傳入任何JavaScript對(duì)象:

◆ read — 必選,一個(gè)用來(lái)執(zhí)行取得依賴監(jiān)控屬性當(dāng)前值的函數(shù)。

◆ write — 可選,如果聲明將使你的依賴監(jiān)控屬性可寫,別的代碼如果這個(gè)可寫功能寫入新值,通過(guò)自定義邏輯將值再寫入各個(gè)基礎(chǔ)的監(jiān)控屬性上。

◆ owner — 可選,如果聲明,它就是KO調(diào)用read或write的callback時(shí)用到的this。查看“管理this”獲取更新信息。

例2:Value轉(zhuǎn)換器

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

  1. viewModel.formattedPrice = ko.dependentObservable({  
  2.  
  3.     read: function () {  
  4.         return "$" + this.price().toFixed(2);  
  5.     },  
  6.  
  7.     write: function (value) {  
  8.         // Strip out unwanted characters, parse as float, then write the raw data back to the underlying "price" observable  
  9.         value = parseFloat(value.replace(/[^\.\d]/g, ""));  
  10.         this.price(isNaN(value) ? 0 : value); // Write to underlying storage  
  11.     },  
  12.     owner: viewModel  
  13. }); 

然后我們綁定formattedPrice到text box上:

  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ù)值。這樣用戶可以看到你的程序有多聰明,來(lái)告訴用戶只能輸入2位小數(shù),否則的話自動(dòng)刪除多余的位數(shù),當(dāng)然也不能輸入負(fù)數(shù),因?yàn)閣rite的callback函數(shù)會(huì)自動(dòng)刪除負(fù)號(hào)。

例3:過(guò)濾并驗(yàn)證用戶輸入

例1展示的是寫操作過(guò)濾的功能,如果你寫的值不符合條件的話將不會(huì)被寫入,忽略所有不包括空格的值。

再多走一步,你可以聲明一個(gè)監(jiān)控屬性isValid 來(lái)表示***一次寫入是否合法,然后根據(jù)真假值顯示相應(yīng)的提示信息。稍后仔細(xì)介紹,先參考如下代碼:

  1. var viewModel = {  
  2.     acceptedNumericValue: ko.observable(123),  
  3.     lastInputWasValid: ko.observable(true)  
  4. };  
  5.  
  6. viewModel.attemptedValue = ko.dependentObservable({  
  7.     read: viewModel.acceptedNumericValue,  
  8.     write: function (value) {  
  9.         if (isNaN(value))  
  10.             this.lastInputWasValid(false);  
  11.         else {  
  12.             this.lastInputWasValid(true);  
  13.             this.acceptedNumericValue(value); // Write to underlying storage  
  14.         }  
  15.     },  
  16.     owner: viewModel  
  17. }); 

… 按照如下格式聲明綁定元素:

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

現(xiàn)在,acceptedNumericValue 將只接受數(shù)字,其它任何輸入的值都會(huì)觸發(fā)顯示驗(yàn)證信息,而會(huì)更新acceptedNumericValue。

備注:上面的例子顯得殺傷力太強(qiáng)了,更簡(jiǎn)單的方式是在<input>上使用jQuery Validation和number class。Knockout可以和jQuery Validation一起很好的使用,參考例子:grid editor 。當(dāng)然,上面的例子依然展示了一個(gè)如何使用自定義邏輯進(jìn)行過(guò)濾和驗(yàn)證數(shù)據(jù),如果驗(yàn)證很復(fù)雜而jQuery Validation很難使用的話,你就可以用它。

依賴跟蹤如何工作的

新手沒(méi)必要知道太清楚,但是高級(jí)開發(fā)人員可以需要知道為什么依賴監(jiān)控屬性能夠自動(dòng)跟蹤并且自動(dòng)更新UI…

事實(shí)上,非常簡(jiǎn)單,甚至說(shuō)可愛。跟蹤的邏輯是這樣的:

◆ 當(dāng)你聲明一個(gè)依賴監(jiān)控屬性的時(shí)候,KO會(huì)立即調(diào)用執(zhí)行函數(shù)并且獲取初始化值。

◆ 當(dāng)你的執(zhí)行函數(shù)運(yùn)行的時(shí)候,KO會(huì)把所有需要依賴的依賴屬性(或者監(jiān)控依賴屬性)都記錄到一個(gè)Log列表里。

◆ 執(zhí)行函數(shù)結(jié)束以后,KO會(huì)向所有Log里需要依賴到的對(duì)象進(jìn)行訂閱。訂閱的callback函數(shù)是重新運(yùn)行你的執(zhí)行函數(shù)。然后回頭重新執(zhí)行上面的***步操作(并且注銷不再使用的訂閱)。

◆ ***KO會(huì)通知上游所有訂閱它的訂閱者,告訴它們我已經(jīng)設(shè)置了新值。

所有說(shuō),KO不僅僅是在***次執(zhí)行函數(shù)執(zhí)行時(shí)候探測(cè)你的依賴項(xiàng),每次它都會(huì)探測(cè)。舉例來(lái)說(shuō),你的依賴屬性可以是動(dòng)態(tài)的:依賴屬性A代表你是否依賴于依賴屬性B或者C,這時(shí)候只有當(dāng)A或者你當(dāng)前的選擇B或者C改變的時(shí)候執(zhí)行函數(shù)才重新執(zhí)行。你不需要再聲明其它的依賴:運(yùn)行時(shí)會(huì)自動(dòng)探測(cè)到的。

另外一個(gè)技巧是:一個(gè)模板輸出的綁定是依賴監(jiān)控屬性的簡(jiǎn)單實(shí)現(xiàn),如果模板讀取一個(gè)監(jiān)控屬性的值,那模板綁定就會(huì)自動(dòng)變成依賴監(jiān)控屬性依賴于那個(gè)監(jiān)控屬性,監(jiān)控屬性一旦改變,模板綁定的依賴監(jiān)控屬性就會(huì)自動(dòng)執(zhí)行。嵌套的模板也是自動(dòng)的:如果模板X render模板 Y,并且Y需要顯示監(jiān)控屬性Z的值,當(dāng)Z改變的時(shí)候,由于只有Y依賴它,所以只有Y這部分進(jìn)行了重新繪制(render)。

3 使用observable數(shù)組

如果你要探測(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)行添加和刪除。

  1. var myObservableArray = ko.observableArray();    // Initially an empty array  
  2. myObservableArray.push('Some value');            // Adds the value and notifies observers 

關(guān)鍵點(diǎn):監(jiān)控?cái)?shù)組跟蹤的是數(shù)組里的對(duì)象,而不是這些對(duì)象自身的狀態(tài)。

簡(jiǎn)單說(shuō),將一對(duì)象放在observableArray 里不會(huì)使這個(gè)對(duì)象本身的屬性變化可監(jiān)控的。當(dāng)然你自己也可以聲明這個(gè)對(duì)象的屬性為observable的,但它就成了一個(gè)依賴監(jiān)控對(duì)象了。一個(gè)observableArray 僅僅監(jiān)控他擁有的對(duì)象,并在這些對(duì)象添加或者刪除的時(shí)候發(fā)出通知。

預(yù)加載一個(gè)監(jiān)控?cái)?shù)組observableArray

如果你想讓你的監(jiān)控?cái)?shù)組在開始的時(shí)候就有一些初始值,那么在聲明的時(shí)候,你可以在構(gòu)造器里加入這些初始對(duì)象。例如:

  1. // This observable array initially contains three objects  
  2. var anotherObservableArray = ko.observableArray([  
  3.     { name: "Bungle", type: "Bear" },  
  4.     { name: "George", type: "Hippo" },  
  5.     { name: "Zippy", type: "Unknown" }  
  6. ]); 

從observableArray里讀取信息

一個(gè)observableArray其實(shí)就是一個(gè)observable的監(jiān)控對(duì)象,只不過(guò)他的值是一個(gè)數(shù)組(observableArray還加了很多其他特性,稍后介紹)。所以你可以像獲取普通的observable的值一樣,只需要調(diào)用無(wú)參函數(shù)就可以獲取自身的值了。 例如,你可以像下面這樣獲取它的值:

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

理論上你可以使用任何原生的JavaScript數(shù)組函數(shù)來(lái)操作這些數(shù)組,但是KO提供了更好的功能等價(jià)函數(shù),他們非常有用是因?yàn)椋?/p>

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

◆ 在數(shù)組操作函數(shù)方面(例如push和splice),KO自己的方式可以自動(dòng)觸發(fā)依賴跟蹤,并且通知所有的訂閱者它的變化,然后讓UI界面也相應(yīng)的自動(dòng)更新。

◆ 語(yǔ)法更方便,調(diào)用KO的push方法,只需要這樣寫:myObservableArray.push(...)。 比如原生數(shù)組的myObservableArray().push(...)好用多了。

下面講解的均是observableArray的讀取和寫入的相關(guān)函數(shù)。

indexOf

indexOf 函數(shù)返回的是***個(gè)等于你參數(shù)數(shù)組項(xiàng)的索引。例如:myObservableArray.indexOf('Blah')將返回以0為***個(gè)索引的***個(gè)等于Blah的數(shù)組項(xiàng)的索引。如果沒(méi)有找到相等的,將返回-1。

slice

slice函數(shù)是observableArray相對(duì)于JavaScript 原生函數(shù)slice的等價(jià)函數(shù)(返回給定的從開始索引到結(jié)束索引之間所有的對(duì)象集合)。 調(diào)用myObservableArray.slice(...)等價(jià)于調(diào)用JavaScript原生函數(shù)(例如:myObservableArray().slice(...))。

操作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ù)

remove和removeAll

observableArray 添加了一些JavaScript數(shù)組默認(rèn)沒(méi)有但非常有用的函數(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ù)組返回

destroy和destroyAll(注:通常只和和Ruby on Rails開發(fā)者有關(guān))

destroy和destroyAll函數(shù)是為Ruby on Rails開發(fā)者方便使用為開發(fā)的:

myObservableArray.destroy(someItem) 找出所有等于someItem的元素并給他們添加一個(gè)屬性_destroy,并賦值為true

myObservableArray.destroy(function(someItem) { return someItem.age < 18 }) 找出所有age屬性小于18的元素并給他們添加一個(gè)屬性_destroy,并賦值為true

myObservableArray.destroyAll(['Chad', 132, undefined]) 找出所有等于'Chad', 123, 或undefined 的元素并給他們添加一個(gè)屬性_destroy,并賦值為true

那么,_destroy是做什么用的?正如我提到的,這只是為Rails 開發(fā)者準(zhǔn)備的。在Rails 開發(fā)過(guò)程中,如果你傳入一個(gè)JSON對(duì)象,Rails 框架會(huì)自動(dòng)轉(zhuǎn)換成ActiveRecord對(duì)象并且保存到數(shù)據(jù)庫(kù)。Rails 框架知道哪些對(duì)象以及在數(shù)據(jù)庫(kù)中存在,哪些需要添加或更新, 標(biāo)記_destroy為true就是告訴框架刪除這條記錄。

注意的是:在KO render一個(gè)foreach模板的時(shí)候,會(huì)自動(dòng)隱藏帶有_destroy屬性并且值為true的元素。所以如果你的“delete”按鈕調(diào)用destroy(someItem) 方法的話,UI界面上的相對(duì)應(yīng)的元素將自動(dòng)隱藏,然后等你提交這個(gè)JSON對(duì)象到Rails上的時(shí)候,這個(gè)元素項(xiàng)將從數(shù)據(jù)庫(kù)刪除(同時(shí)其它的元素項(xiàng)將正常的插入或者更新)。

原文:http://www.cnblogs.com/TomXu/archive/2011/11/22/2256820.html

【編輯推薦】

  1. Knockout應(yīng)用開發(fā)指南之入門介紹
  2. 2011年度***jQuery插件揭曉(附下載)
  3. 如何更好的面試JavaScript工程師
  4. 一位反JavaScript主義者的覺(jué)醒
  5. 如何做到對(duì)JavaScript的API兼容
責(zé)任編輯:陳貽新 來(lái)源: 湯姆大叔的博客
相關(guān)推薦

2011-12-05 15:44:45

Knockout

2011-12-05 14:50:13

Knockout

2012-01-04 16:21:11

2011-11-29 16:38:58

Knockout

2011-11-30 16:29:41

2012-01-04 16:11:49

Knockout

2011-12-05 15:02:21

Knockout

2011-04-15 14:22:20

圖片操作UIBlackBerry

2011-04-18 11:00:34

使用音頻BlackBerry

2011-06-07 09:10:41

BlackBerry 開發(fā)

2011-04-15 15:16:28

使用圖像對(duì)象畫圖BlackBerry

2011-07-25 16:21:22

Sencha touc

2022-08-02 08:01:09

開發(fā)插件Chrome前端技術(shù)

2011-04-15 16:05:00

監(jiān)聽UI對(duì)象的改變BlackBerry

2012-03-26 09:27:40

谷歌安卓開發(fā)谷歌安卓

2011-06-09 18:24:36

QT Wince

2023-05-15 18:44:07

前端開發(fā)

2009-06-24 16:30:21

JSF組件模型

2013-10-09 09:10:28

移動(dòng)應(yīng)用開發(fā)NativeHybrid

2024-08-01 11:10:52

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

久久av最新网址| 四虎影视精品| 玉米视频成人免费看| 国产91视觉| 99精品人妻国产毛片| 色婷婷亚洲mv天堂mv在影片| 日韩三级在线免费观看| 国产高清精品在线观看| 在线观看h片| 国产高清亚洲一区| 国产精品黄色av| 亚洲一级生活片| 九九视频免费观看视频精品| 欧美一区二区在线免费播放| 91国视频在线| 在线观看电影av| 日本一区二区三区在线不卡| 成人xxxxx色| 在线观看毛片av| 99在线|亚洲一区二区| 久久九九有精品国产23| 毛茸茸多毛bbb毛多视频| 成人黄色理论片| 一本一道综合狠狠老| 日本高清xxxx| 香蕉视频网站在线观看| 91在线一区二区| 99国产超薄肉色丝袜交足的后果| а中文在线天堂| 国产日韩欧美一区二区三区在线观看| 久久综合免费视频| 中字幕一区二区三区乱码 | 国产精品a久久久久久| 国产小视频在线观看免费| 日韩情爱电影在线观看| 国产丝袜视频一区| 美女黄色一级视频| 我要色综合中文字幕| 欧美丰满高潮xxxx喷水动漫| www.色就是色| 一区二区三区短视频| 亚洲午夜精品久久久久久久久| 日本黄色播放器| av小片在线| 中文字幕久久午夜不卡| 日本婷婷久久久久久久久一区二区| 神马久久久久久久久久| 国产精品中文有码| 91久久久久久国产精品| 一本大道伊人av久久综合| 日本伊人色综合网| 国产精品视频xxx| 中文永久免费观看| 蜜臀va亚洲va欧美va天堂 | 色妞一区二区三区| 夜夜春很很躁夜夜躁| 视频一区中文| 国产一区二区日韩| 一本在线免费视频| 久久理论电影| 久久久精品久久| 中文字幕在线观看成人| 欧美三级网页| 亚州av一区二区| 精品人妻一区二区三区免费看| 性一交一乱一区二区洋洋av| 日本免费在线精品| 波多野结衣一区二区三区在线| 日韩精品福利网| 国产精品综合网站| 国产肥老妇视频| 成人视屏免费看| 免费电影一区| eeuss影院在线观看| 亚洲欧美日韩国产另类专区| 国产成人永久免费视频| 岛国片av在线| 色哟哟精品一区| 五月婷婷六月丁香激情| 视频精品二区| 亚洲精品久久久久中文字幕二区| 最新中文字幕视频| 久久视频在线| 欧美精品videossex性护士| 欧美三级一区二区三区| 免费成人在线影院| av一区二区三区免费| 亚洲欧美综合在线观看| 国产精品成人网| 欧妇女乱妇女乱视频| 日本а中文在线天堂| 欧美系列一区二区| 美女被爆操网站| 亚洲男人都懂第一日本| 久久九九亚洲综合| 在线精品免费视| 国产美女精品人人做人人爽| 精品欧美一区二区三区久久久| 触手亚洲一区二区三区| 亚洲一区二区三区自拍| the porn av| 超碰成人在线观看| 永久555www成人免费| 青青草原在线免费观看视频| 久久国产毛片| 91九色视频在线观看| 邻居大乳一区二区三区| 亚洲日本成人在线观看| 久久久久久久久久久久久国产精品| 图片一区二区| 亚洲女在线观看| 免费在线观看av网址| 美女网站久久| 国产一区二区精品在线| 成人在线观看免费网站| 91高清视频在线| 成人性生活免费看| 你懂的网址国产 欧美| 国产精品第三页| 三级视频网站在线| 亚洲va欧美va天堂v国产综合| 性生活免费在线观看| 亚洲精品亚洲人成在线观看| 欧美国产在线电影| 国产又粗又猛又爽又黄的视频一| 久久综合狠狠综合久久综合88| 国产激情在线看| 日韩成人一区| 上原亚衣av一区二区三区| 一级片免费在线播放| 97se亚洲国产综合自在线| 欧美国产日韩激情| 88久久精品| 欧美精品免费播放| 国产伦一区二区| 国产精品理伦片| 亚洲最大综合网| 国产乱码精品一区二区三区四区| 欧美中文字幕在线观看| 天堂网在线中文| 午夜a成v人精品| 精品无码国产一区二区三区51安| 国内综合精品午夜久久资源| 成人三级视频在线观看一区二区| caopo在线| 91精品国产免费久久综合| 午夜激情福利网| 国产精品一二三| 人人妻人人澡人人爽欧美一区| 青草伊人久久| 色综合五月天导航| 懂色av蜜臀av粉嫩av分享吧 | 中文字幕精品无码一区二区| 久久这里只有精品首页| 欧美 日韩精品| 精品理论电影在线| 国产日韩精品一区二区| 免费黄色网页在线观看| 91精品久久久久久久91蜜桃| www.超碰在线观看| 成人黄页在线观看| 男女高潮又爽又黄又无遮挡| 中文字幕精品影院| 国产精品久久久久久av福利软件| 99reav在线| 91麻豆精品国产91久久久更新时间| 在线观看美女av| 岛国精品在线观看| 国产免费成人在线| 欧美色图激情小说| 国产综合色香蕉精品| 97影院秋霞午夜在线观看| 日韩一区二区三区四区五区六区| 18精品爽视频在线观看| 91麻豆成人久久精品二区三区| 欧美成人黄色网址| 亚洲精品电影| 免费成人看片网址| 99久久这里有精品| 久久久最新网址| 国产专区在线播放| 欧美一级爆毛片| 中文字幕精品三级久久久 | 日韩hd视频在线观看| 黄色一级视频免费看| 1区2区3区欧美| 在线天堂www在线国语对白| 日本亚洲欧美天堂免费| 精品免费久久久久久久| 九九在线精品| 7777精品伊久久久大香线蕉语言 | 不卡在线一区二区| 成人欧美一区二区| 综合在线影院| 欧美大肥婆大肥bbbbb| 国产在线黄色| 精品欧美久久久| 91porny九色| 亚洲一级片在线观看| аⅴ天堂中文在线网| 成人午夜视频福利| 色播五月激情五月| 香蕉久久夜色精品| 超碰超碰超碰超碰超碰| 国产精品美女久久久久久不卡| 亚洲一区二区三区sesese| 一个人www视频在线免费观看| 久久影视免费观看| 超碰在线影院| 国产婷婷97碰碰久久人人蜜臀| 999av视频| 欧美网站大全在线观看| www成人在线| 亚洲一二三四在线| 一本一本久久a久久| 久久精品亚洲精品国产欧美 | 午夜视频一区二区在线观看| 国产精品久久久av久久久| 蜜桃视频m3u8在线观看| 欧美肥婆姓交大片| 国产黄a三级三级三级av在线看 | 97超碰资源站在线观看| 这里只有精品视频| 毛片免费在线播放| 亚洲精品成人免费| 高潮毛片7777777毛片| 91精品国产欧美一区二区18| 怡红院男人天堂| 色视频一区二区| 久久久久久久久久影院| 午夜欧美一区二区三区在线播放| 裸体武打性艳史| 国产精品视频看| 亚洲精品一区二区三区影院忠贞| 91麻豆福利精品推荐| 一起草在线视频| 不卡电影一区二区三区| 亚洲成人福利视频| 国产v综合v亚洲欧| wwwxxx色| 成人在线一区二区三区| 日本中文字幕有码| 国产91在线|亚洲| www.四虎在线| 成人激情午夜影院| 日本黄色免费观看| 91免费视频观看| 97超碰在线资源| 日本一区二区三区国色天香| 在线免费观看视频| 国产欧美日韩不卡免费| 在线观看亚洲大片短视频| 国产欧美一区二区精品久导航 | sdde在线播放一区二区| 日韩欧美第二区在线观看| 精品国产一区二区三区噜噜噜 | 在线激情网站| 久久久www成人免费精品| 国产精品一区二区三区视频网站| 欧美成人精品一区二区三区| 欧美人与性动交α欧美精品济南到| 久久久久久久激情视频| 日韩脚交footjobhd| 日本精品久久中文字幕佐佐木 | 亚洲精品欧美一区二区三区| 欧美成人精品午夜一区二区| 成人性色av| 亚洲免费专区| 伊人久久婷婷色综合98网| 欧美在线高清| 内射国产内射夫妻免费频道| 老**午夜毛片一区二区三区 | 久久人体av| 2014亚洲精品| 丝袜美腿综合| 中文字幕在线亚洲精品| 国产一区日韩一区| 日韩av资源在线| 紧缚奴在线一区二区三区| 色欲欲www成人网站| 久久日一线二线三线suv| 任我爽在线视频| 亚洲国产成人精品视频| 中文字幕久久网| 精品日韩在线一区| av电影在线网| 久久久久久国产精品三级玉女聊斋| 欧美成人资源| 亚洲淫片在线视频| 亚洲涩涩av| 日韩人妻一区二区三区蜜桃视频| 在线亚洲精品| 色综合五月婷婷| 久久男人中文字幕资源站| 中文字幕在线有码| 欧美亚洲一区二区在线| 亚洲av无码一区二区乱子伦| 一区二区三欧美| 精精国产xxxx视频在线中文版| 国产精品va在线| 欧美美女黄色| 成人毛片100部免费看| 免费高清在线视频一区·| 少妇一级淫片免费放播放| 中文字幕一区二区三区精华液| 国产69精品久久久久久久久久| 7777精品伊人久久久大香线蕉超级流畅| 天堂av2024| 欧美乱人伦中文字幕在线| 久久91导航| 国产综合精品一区二区三区| 99精品视频精品精品视频 | 97人人做人人爽香蕉精品| 国产精品乱码一区二区三区| 四季av一区二区凹凸精品| 丝袜老师办公室里做好紧好爽 | 亚洲精品一级| 国产91在线免费观看| 国产精品乱码人人做人人爱 | 午夜宅男久久久| 精品人妻一区二区免费| 亚洲精品免费电影| 一级特黄色大片| 亚洲网址你懂得| 欧美xxx视频| 免费精品视频一区| 99香蕉国产精品偷在线观看 | 久久久久久97三级| 久久久国产高清| 精品国产一区二区三区忘忧草| 超碰在线观看免费| 91精品久久久久久久久久入口| 精品国产中文字幕第一页| av免费网站观看| 久久先锋影音av| 免费观看日批视频| 亚洲天堂av在线播放| 户外露出一区二区三区| 欧美极品一区| 另类图片国产| 无码 人妻 在线 视频| 日本高清免费不卡视频| 九色在线播放| 国产精品福利无圣光在线一区| 国产精品亚洲人成在99www| 国产精品天天av精麻传媒| 欧美激情一区二区| 一级片视频免费| 久久综合伊人77777蜜臀| 玖玖精品一区| 日韩精品视频在线观看视频 | 老鸭窝亚洲一区二区三区| 国产精品揄拍100视频| 91搞黄在线观看| 欧美极品视频| 91麻豆国产精品| 欧美午夜不卡| 好男人香蕉影院| 欧美性高潮在线| 成人在线播放视频| 91精品久久久久久久久中文字幕| 亚洲欧美综合久久久| 亚洲午夜精品在线观看| 亚洲成人av一区二区| 人人妻人人澡人人爽人人欧美一区| 26uuu另类亚洲欧美日本一| 久久综合影院| 久久久久xxxx| 亚洲一区二区在线免费看| 四虎在线视频免费观看| 国产精品户外野外| 欧美精品97| 免费的av网站| 欧美视频在线一区二区三区| 美女羞羞视频在线观看| 动漫精品视频| 久热精品在线| 午夜剧场免费在线观看| 日韩av在线免费| 国产精品高潮久久| 人妻av无码专区| 国产欧美精品在线观看| www.国产.com| 日本一欧美一欧美一亚洲视频| 久久免费大视频| 女人被狂躁c到高潮| 欧美精品高清视频| 日本蜜桃在线观看视频| 在线免费观看一区二区三区| 国产 日韩 欧美大片| 男人天堂视频网| 久久99精品视频一区97| 欧美激情在线精品一区二区三区| 久久久久久久久久一区二区| 性做久久久久久免费观看| 国产高清自拍视频在线观看| 成人国产一区二区| 日韩精品一卡二卡三卡四卡无卡| 欧美成人片在线观看| 国产亚洲综合久久|