可賦值的計算監控屬性
可賦值的計算監控屬性是非常專業的,大多數情況下一般用不到,初學者可以跳過這一節
通常情況下,計算監控屬性一般情況下是只讀的。我們可以通過使用自己的回調函數讓計算監控屬性變為可賦值狀態。
您可以用自己的定制邏輯讓計算監控屬性可寫。就像將空屬性,可以使用一個模型對象的鏈接的語法進行賦值。例如,myViewModel.fullName('Joe Smith').age(50)
。
示例1:分解用用戶輸入
讓我們回到經典的例子“名+姓=全名”例如,fullName是計算監控屬性,用戶可以直接編輯全名,再根據用戶輸入的全名解析並將值分別賦值給firstName和lastName這兩個監控屬性。
UI源碼:
<div>First name: <span data-bind="text: firstName"></span></div> <div>Last name: <span data-bind="text: lastName"></span></div> <div class="heading">Hello, <input data-bind="textInput: fullName"/></div>
視圖模型代碼:
function MyViewModel() { this.firstName = ko.observable('Planet'); this.lastName = ko.observable('Earth'); this.fullName = ko.pureComputed({ read: function () { return this.firstName() + " " + this.lastName(); }, 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" } }, owner: this }); } ko.applyBindings(new MyViewModel());
本例中,使用了pureComputed(當然也可以使用Computed)的read和write回掉函數,其中write回掉函數將計算監控屬性進行解析,並分別賦值給firstName和lastName這兩個監控屬性。
示例2:全選或取消全選項目
當使用復選框來選擇項目的時候需要包括全選或取消全選的所有項目的方法。
UI源碼:
<div class="heading"> <input type="checkbox" data-bind="checked: selectedAllProduce" title="Select all/none"/> Produce </div> <div data-bind="foreach: produce"> <label> <input type="checkbox" data-bind="checkedValue: $data, checked: $parent.selectedProduce"/> <span data-bind="text: $data"></span> </label> </div>
視圖模型源碼:
function MyViewModel() { this.produce = [ 'Apple', 'Banana', 'Celery', 'Corn', 'Orange', 'Spinach' ]; this.selectedProduce = ko.observableArray([ 'Corn', 'Orange' ]); this.selectedAllProduce = ko.pureComputed({ read: function () { // Comparing length is quick and is accurate if only items from the // main array are added to the selected array. return this.selectedProduce().length === this.produce.length; }, write: function (value) { this.selectedProduce(value ? this.produce.slice(0) : []); }, owner: this }); } ko.applyBindings(new MyViewModel());
示例3:值轉換器
有時候,可能界面上的值並非是要傳遞到數據庫中的值。例如,您可能希望存儲原始浮點值,但是在用戶編輯的時候讓他跟一個貨幣符號。可以通過如下方式來進行轉換:
UI源碼:
<div>Enter bid price: <input data-bind="textInput: formattedPrice"/></div> <div>(Raw value: <span data-bind="text: price"></span>)</div>
視圖模型源碼:
function MyViewModel() { this.price = ko.observable(25.99); this.formattedPrice = ko.pureComputed({ read: function () { return '$' + this.price().toFixed(2); }, write: function (value) { // Strip out unwanted characters, parse as float, then write the // raw data back to the underlying "price" observable value = parseFloat(value.replace(/[^\.\d]/g, "")); this.price(isNaN(value) ? 0 : value); // Write to underlying storage }, owner: this }); } ko.applyBindings(new MyViewModel());
現在,只要用戶進入一個新的價格,文本框會立即更新,以顯示貨幣符號和兩位小數格式,這是一種很好的用戶體驗,就算用戶多輸入幾位小數,多出兩位小數的部分也會被自動刪除。同樣,它們不能輸入負值,因為write回掉函數會去掉
任何減號。
示例4:篩選和驗證用戶輸入
在示例1中,描述了如何編寫可賦值的計算監控屬性,但是如果用戶在不輸入空格的情況下,將會出現LastName不被賦值的情況。
本例中,將使用KO的驗證機制,保證在用戶輸入無效值的時候給出錯誤提示:
UI源碼:
<div>Enter a numeric value: <input data-bind="textInput: attemptedValue"/></div> <div class="error" data-bind="visible: !lastInputWasValid()">That's not a number!</div> <div>(Accepted value: <span data-bind="text: acceptedNumericValue"></span>)</div>
視圖模型源碼:
function MyViewModel() { this.acceptedNumericValue = ko.observable(123); this.lastInputWasValid = ko.observable(true); this.attemptedValue = ko.pureComputed({ read: this.acceptedNumericValue, write: function (value) { if (isNaN(value)) this.lastInputWasValid(false); else { this.lastInputWasValid(true); this.acceptedNumericValue(value); // Write to underlying storage } }, owner: this }); } ko.applyBindings(new MyViewModel());
如上述源碼,acceptedNumericValue
將只包含數值,如果鍵入其他任何值都會觸發一個驗證消息,而不更新的UI界面的acceptedNumericValue
。
總結
對於上述示例,有些時候可能使用Jquery驗證會更加簡單便利,有些時候可能KO的計算監控屬性驗證更加簡單,這需要你視情況而選擇某種技術來解決問題。大多數新情況下都是配合KO和Jquery使用,上述示例只是描述一下KO的這些機制作用。切勿生搬硬套。要靈活運用。