1. 程式人生 > >(更新)knockout.js學習——1.8例子——繫結的詳細語法

(更新)knockout.js學習——1.8例子——繫結的詳細語法

knockout.js
1、click
如果應用於a標籤,會阻止a的預設href動作。如果需要保持href,則在click事件後面加上return true。
clickBubble:false阻止冒泡。


event:
data-bind="event:{mouseover:,mouseout:}"
加上類名:
data-bind="css:{'classname':showOrNot}


if和ifnot表示是否顯示該部分。
visible
enable




2、submit繫結


submit繫結會預設阻止表單提交的動作。
如果要保持表單提交的動作,加上:return true;


使用submit而不是click的好處是:submit可以捕捉到輸入後enter鍵操作(等價於submit,可以觸發submit對應事件)




3、enable繫結、disable繫結


用於input\textarea\select
當選中時,繫結對應的true或false改變,其他對應按鈕的enable根據這個值發生改變。即:一個輸入或選擇的選中,對應了另一個按鈕的enable。


可以使用任意表達式:
<button data-bind="enable: parseAreaCode(viewModel.cellphoneNumber()) != '555'">
    Do something
</button>


4、value繫結


用於input\textarea\select
不用於radio和checkbox,這兩個使用checked繫結。
ko會在焦點改變或輸入值改變時嘗試自動更新。也可以使用valueUpdate來進行繫結。


valueUpdate:'input'    // 當input或textarea元素改變。支援一般瀏覽器
valueUpdate:'keyup'
valueUpdate:'keypress'
valueUpdate:'afterkeydown'      // 支援舊瀏覽器
valueUpdate:'valueAllowUnset'   // 只用於使用value來控制select元素的選擇時






一般,當在select元素
使用value繫結,意味著描述哪一個option被選擇。
但是,如果在model中設定的是value不對應任何一個option選擇將會怎麼樣呢?
ko的預設行為是重寫model value 來重置已經選擇的下拉列表,因此阻止model和UI的同步。解決方法:在select中設定valueAllowUnset:true。在這種情況下,無論何時你的model value沒有在select中展現,select展現空白。當用戶選擇下拉列表時,value值會對應選擇。


簡單來說:在viewmodel中寫了value的初始值,但是select仍然顯示空白,就是因為設定了valueAllowUnset:true。
如果沒有寫valueAllowUnset:true,ko會預設value的值為undefined。將會匹配optionsCaption進入下拉列表。


<p>
    Select a country:
    <select data-bind="options: countries,
                       optionsCaption: 'Choose one...',
                       value: selectedCountry,
                       valueAllowUnset: true"></select>
</p>
 
<script type="text/javascript">
    var viewModel = {
        countries: ['Japan', 'Bolivia', 'New Zealand'],
        selectedCountry: ko.observable('Latvia')
    };
</script>




5、hasFocus繫結


當有焦點和失去焦點時,hasFocus值對應為true和false。
點選變成編輯框,失去焦點為顯示區域:
寫法一:
<p>
    Name: 
    <b data-bind="visible: !editing(), text: name, click: edit">&nbsp;</b>
    <input data-bind="visible: editing, value: name, hasFocus: editing" />
</p>
<p><em>Click the name to edit it; click elsewhere to apply changes.</em></p>


function PersonViewModel(name) { // 這種形式在內部的屬性需加上this.字首,function中可以帶上引數
    // Data
    this.name = ko.observable(name);
    this.editing = ko.observable(false);
         
    // Behaviors
    this.edit = function() { this.editing(true) }
}
 
ko.applyBindings(new PersonViewModel("Bert Bertington"));




寫法二:
點選名字為輸入框。<br />
    <p>name:
 <b data-bind="text: editValue, click: showNot, visible: !normal()"></b>
 <input type="text" data-bind="value: editValue, visible: normal, hasFocus: normal" />
    </p>
 
<script type="text/javascript">
    var viewModel = {
        normal: ko.observable(false),
        editValue: ko.observable("Your name"),
        showNot:function(){this.normal(true);},
    };
 ko.applyBindings(viewModel);
</script>






6、checked繫結


checked繫結,用於checkbox和radio。
其他的text控制元件,下拉列表,非check的表單控制元件,都用value繫結。
當提供的是ko.observableArray陣列時,會自動與check相關的元素對應,沒有包括在內的則不選中。
radio:
只有當提供的ko.observable的引數和radio的html中value值相等時,才會被選中。
當名字值一樣時,多個radio只能單選。
參考flavorGroup。


checkedValue繫結:
定義了checkbox或radio的value值,是可以繫結的。而不是html中value定義的值。當需要對value值動態變化或物件化或傳遞引數。




在一下例子中,當checkbox被check的時候,條目物件本身而不是itemName條目名字字串被包括在chosenItems陣列中。
<!-- ko foreach: items -->
    <input type="checkbox" data-bind="checkedValue: $data, checked: $root.chosenItems" />
    <span data-bind="text: itemName"></span>
<!-- /ko -->
 
<script type="text/javascript">
    var viewModel = {
        items: ko.observableArray([
            { itemName: 'Choice 1' },
            { itemName: 'Choice 2' }
        ]),
        chosenItems: ko.observableArray()
    };
</script>




7、options繫結


只能用於select標籤。
繫結的是option下拉列表的每一個條目。
設定的值必須是一個數組,select元素將會展現陣列中每一個條目和select中對應的每一個下拉條目。


在多下拉選項展現的列表中,使用 selectedOptions繫結。
在單選擇下拉中,可以使用value繫結。




(1)options:


在viewmodel中提供一個observable array。
在html中只需寫select。對應ko會增加option到select中,並覆蓋本來如果寫了的option。


如果引數值是一組字串,不需要給出其他引數。select元素會為每一個option展現一個字串值。
如果想要讓使用者從任意的js物件陣列中選擇,可以參考optionsText和optionsValue引數。


(2)optionsCaption:


如何避免select預設選中一項。
optionsCaption:"select an item......."
並預設賦值為:undefined




(3)optionsText:


如何繫結options到一個任意js物件陣列中,而不是字串中。
在這種情況下,你應該選擇這個物件的屬性作為text展示在下拉列表中。方法:optionsText:object.name   optionsText:this.property
通過傳遞optionsText詳細說明物件的屬性。




(4)optionsValue:
對應了option的value值,可觀測。當選擇一個option時,就預設選擇/更新了value值。
詳細說明物件屬性的哪一部分用來設定ko生成的option元素的value屬性。
可以通過詳細設定一個js function來設定這個value。這個function接受選擇的item作為唯一的論據,並且返回一個字串作為option的value屬性。


典型的,你可能只想用optionsValue作為一種確認ko可以正確保留selection的方式,當你更新可用options時。
比如,當你通過ajax訪問重複獲取列表中car物件
,想要確認car已經儲存,你可能需要設定optionsValue到carId,或每一個car物件所擁有的任何唯一的識別符號。否則ko不會知道哪一個以前的car物件對應新的。


(5)optionsIncludeDestroyed


有時候你可能要標記一個數組條目進行刪除,但是並不是真的刪除這部分記錄。
這就是non-destructive 刪除。
如果要顯示銷燬的條目,詳細說明引數如下:
<select data-bind="options:,optionsIncludeDestroyed:true"></select>


(6)optionsAfterRender


定製回撥函式。


(7)selectedOptions


(8)valueAllowUnset
預設顯示空白。




9、selectedOptions繫結


應該是陣列。
當前選中項繫結。




10、uniqueName繫結 uniqueName:true/false


使元素獲得一個唯一的name屬性。
如:
   <input type="checkbox"  data-bind="uniqueName: true "/>




<script type="text/javascript">
    var viewModel = {
    };  
    ko.applyBindings(viewModel);
</script>


輸出顯示效果:

<input name="ko_unique_1" type="checkbox" value="sfwf" data-bind="value:kovalue,uniqueName: true ">


<input name="ko_unique_2" type="checkbox" value="sfwf" data-bind="value:kovalue,uniqueName: true ">



自動加上了name屬性,且唯一。






二、繫結語法


1、跳過幫定值


可以指定沒有值的繫結,這將給繫結一個未定義的值。比如:
<span data-bind="text">Text that will be cleared when bindings are applied.</span>


2、繫結的語境、上下文


一個繫結上下文是一個擁有資料的物件。這個資料可以參考繫結獲得。


當使用繫結時,ko自動創造和管理層次結構,繫結上下文。
層次結構中的root級別是指你提供給ko.applyBindings(viewModel)的viewModel引數。
這樣,每次你使用一個如with、foreach控制流,都會創造一個到巢狀檢視data的子繫結上下文。


繫結上下文提供一下可以應用到繫結中的屬性:


(1)$parent
這是在父上下文語境中的檢視物件,可以迅速跳到當前上下文的外層。
在root上下文背景,$parent是undefined狀態。


(2)$parents
這是一個展現所有parent的view model的陣列
$parents[0]當前$parent
$parents[1]上一層parent
$parents[2]上上一層parent


(3)$root
這是一個當前上下文背景中的view model物件。
在root上下文中,$data和$root是相同的。
在一個巢狀繫結上下文,這個引數用來設定當前data item。
當範文viewmodel本身而不是屬性時,可以用$data。
比如:


當前 with:person繫結,$data是指person。




(4)$index(只在和foreach繫結一起時有效)
$index是一個可觀測值,從0開始,當item的index改變時更新。


(5)$parentContext
是指繫結上下文物件所在的parent層級。
與$parent不同,指的是data所在parent層級,而不是繫結上下文所在parent層級。


(6)$rawData、$context、$element






三、template繫結


1、本地模板


2、基於字串的模板(第三方)




(1)展現一個名字模板:
<h2>Participants</h2>
Here are the participants:
<div data-bind="template: { name: 'person-template', data: buyer }"></div>
<div data-bind="template: { name: 'person-template', data: seller }"></div>
 
<script type="text/html" id="person-template">
    <h3 data-bind="text: name"></h3>
    <p>Credits: <span data-bind="text: credits"></span></p>
</script>
 
<script type="text/javascript">
     function MyViewModel() {
         this.buyer = { name: 'Franklin', credits: 250 };
         this.seller = { name: 'Mario', credits: 5800 };
     }
     ko.applyBindings(new MyViewModel());
</script>




(2)foreach的模板繫結
<h2>Participants</h2>
Here are the participants:
<div data-bind="template: { name: 'person-template', foreach: people }"></div>
 
<script type="text/html" id="person-template">
    <h3 data-bind="text: name"></h3>
    <p>Credits: <span data-bind="text: credits"></span></p>
</script>
 
 function MyViewModel() {
     this.people = [
         { name: 'Franklin', credits: 250 },
         { name: 'Mario', credits: 5800 }
     ]
 }
 ko.applyBindings(new MyViewModel());




相同效果:
<div data-bind="foreach: people">
    <h3 data-bind="text: name"></h3>
    <p>Credits: <span data-bind="text: credits"></span></p>
</div>




(5)as指定別名。當指定as時,在使用foreach時,低層級的訪問高層級的物件可以用別名代替,而不是用$parent


(6)afterRender、afterAdd、beforeRemove


 (7)動態選擇模板


<ul data-bind='template: { name: displayMode,
                           foreach: employees }'> </ul>
 
<script>
    var viewModel = {
        employees: ko.observableArray([
            { name: "Kari", active: ko.observable(true) },
            { name: "Brynn", active: ko.observable(false) },
            { name: "Nora", active: ko.observable(false) }
        ]),
        displayMode: function(employee) {
            // Initially "Kari" uses the "active" template, while the others use "inactive"
            return employee.active() ? "active" : "inactive";
        }
    };
 
    // ... then later ...
    viewModel.employees()[1].active(true); // Now "Brynn" is also rendered using the "active" template.
</script>










(8)使用 jQuery.tmpl模板。2011後就不再更新,建議不使用。使用本地模板(比如foreach,if,with等)。
順序:
<!-- First jQuery -->     <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<!-- Then jQuery.tmpl --> <script src="jquery.tmpl.js"></script>
<!-- Then Knockout -->    <script src="knockout-x.y.z.js"></script>


(9)利用Underscore.js模板引擎




四、自定義模板


1、註冊繫結


ko.bindingHandlers


2、ko.bindingHandlers.yourBindingName = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever the associated observable changes value.
        // Update the DOM element based on the supplied values here.
    }
};
<div data-bind="yourBindingName: someValue"> </div>




update:


(1)element:dome element
(2)valueAccessor:一個js功能,可以得到現在model繫結的屬性。可以不用傳遞任何引數通過valueAccessor()得到,可以接受observable和一般values,呼叫ko.unwrap得到返回值。
(3)allBindings:一個javascript物件,可以用來訪問所有繫結dom元素的model values。
比如檢索name繫結:allBindings.get('name')或allBindings.has('name')
(4)viewModel:被bindingContext.$data或bindingContext.$rawData代替,用來訪問view model。
(5)bindingContext包括:$parent,$parents,$root用來訪問上下文繫結的祖先元素。




動畫過渡:
ko.bindingHandlers.slideVisible = {
    update: function(element, valueAccessor, allBindings) {
        // First get the latest data that we're bound to
        var value = valueAccessor();
 
        // Next, whether or not the supplied model property is observable, get its current value
        var valueUnwrapped = ko.unwrap(value);
 
        // Grab some more data from another binding property
        var duration = allBindings.get('slideDuration') || 400; // 400ms is default duration unless otherwise specified
 
        // Now manipulate the DOM element
        if (valueUnwrapped == true)
            $(element).slideDown(duration); // Make the element visible
        else
            $(element).slideUp(duration);   // Make the element invisible
    }
};




首先,獲取當前繫結的data物件。
其次,獲取data的繫結值。