Knockoutjs 學(xué)習(xí)系列(二)花式捆綁
在上一篇Knockoutjs 學(xué)習(xí)系列(一)ko初體驗(yàn)文章中提到,ko中的 data-bind = "XX:OO"綁定大法除了可以綁定text、value等內(nèi)容,還可以綁定visible、style等外觀屬性,也可以綁定click、textInput等各種事件,甚至還能控制程序流程。各種花式捆綁,絕對(duì)滿足你的幻想。
下面簡(jiǎn)單講講各種綁定的使用,主要根據(jù)被綁定的屬性分成表現(xiàn)類、流程類和交互類三種。
表現(xiàn)類屬性
表現(xiàn)類的綁定屬性有visible、text、html、css、style、attr幾種,除了css表示css的class之外,其他都很好理解。當(dāng)然了,style里面的命名要與js一致,要去掉-改成駝峰命名,示范如下:
<!--HTML code--> <div data-bind="visible: shouldShowMessage">You will see this message only when "shouldShowMessage" holds a true value.</div> <div>Today's message is: <span data-bind="text: myMessage"></span></div> <div data-bind="html: details"></div> <div data-bind="css: { profitWarning: currentProfit() < 0 }">CSS class binding test</div> <div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">CSS style binding test</div> <a data-bind="attr: { href: url, title: urltitle }">Report</a> // js code var viewModel = { shouldShowMessage: ko.observable(true), // Message initially visible myMessage: ko.observable(), // Initially blank details: ko.observable(), // Initially blank currentProfit: ko.observable(150000), // Positive value, so initially we don't apply the "profitWarning" class currentProfit: ko.observable(150000), // Positive value, so initially black url: ko.observable("year-end.html"), urltitle: ko.observable("Report including final year-end statistics") }; ko.applyBindings(viewModel); // apply binds
效果是這樣的:
上一篇文章里面也說過,XXOO里面除了傳單個(gè)的屬性,也可以傳JSON對(duì)象,也就是說可以組合綁定屬性,比如說:
<!--HTML code--> <div data-bind="{visible: shouldShowMessage, text: myMessage, css: { profitWarning: currentProfit() < 0 }}"> You will see this message only when "shouldShowMessage" holds a true value. </div>
效果當(dāng)然是這樣的:
表現(xiàn)類的設(shè)置比較簡(jiǎn)單,要注意的一點(diǎn)就是:很多表現(xiàn)類的屬性并不需要?jiǎng)討B(tài)變化,這個(gè)時(shí)候可以利用viewModel中設(shè)置實(shí)現(xiàn)數(shù)據(jù)的集中初始化,但是不要把他們?cè)O(shè)置成可觀察者,如:
// js code var viewModel = { shouldShowMessage: ko.observable(true), // Message initially visible myMessage: '這段文字不需要?jiǎng)討B(tài)更新' // Initially blank };
流程類屬性
流程類包括foreach、if、ifnot、with和比較高級(jí)的"component”綁定,if 和 ifnot 與 visible類似,差別就是:if 會(huì)直接從DOM中移除相應(yīng)的組件,而visible只是控制隱藏顯示,組件還是在DOM里面的。with 跟 js 中的 with 也是一樣的效果,就是延長(zhǎng)了作用域鏈,簡(jiǎn)單的來說就是在變量前加了個(gè)'前綴.'。這里只介紹一下foreach,component放到和模板綁定一起介紹。
看看代碼:
<!--HTML code--> <p>測(cè)試foreach綁定</p> <ul data-bind="foreach: people"> <li> No.<span data-bind="text: $index"> </span> people's name: <span data-bind="text: name"> </span> <a href="#" data-bind="click: $parent.removePeople">RemovePeople</a> <a href="#" data-bind="click: remove">Remove</a> </li> </ul> <input type="button" data-bind="click: addPeople" value="Add" /> var listModel = function () { //設(shè)置people數(shù)組的值(people實(shí)際上是函數(shù)數(shù)組),使用foreach可以遍歷數(shù)組對(duì)象 //ul,li對(duì)應(yīng)的是 people和people的子項(xiàng),所以在li內(nèi)部綁定時(shí),作用域是在people子項(xiàng){name……}中,為了調(diào)用people外部的removePeople需要用到$parent //如果是調(diào)用內(nèi)部的remove,remove中的this為{name……}對(duì)應(yīng)當(dāng)前l(fā)i項(xiàng),作用域?yàn)楫?dāng)前域則不用加 $parent。 this.people = ko.observableArray([ {name: "Mark Zake", remove: function () { that.people.remove(this); //注意當(dāng)前對(duì)象(就是{name……})和作用域,不用管HTML標(biāo)簽,純js理解就簡(jiǎn)單了 }}, {name: "James Lebo", remove: function () { that.people.remove(this); }}, {name: "Green Deny", remove: function () { that.people.remove(this); }} ]); //addPeople內(nèi)部調(diào)用了同級(jí)people的方法,this會(huì)發(fā)生改變,應(yīng)該預(yù)先保存this傳進(jìn)去。 var that = this; this.addPeople = function () { that.people.push({ name: new Date().toDateString(), remove: function () { that.people.remove(this); }}); }; //remove的對(duì)象是整個(gè) li標(biāo)簽,也就是 a標(biāo)簽的父對(duì)象。實(shí)際上要執(zhí)行的是 listModel.people.remove(a.parent) this.removePeople = function() { that.people.remove(this); } }; ko.applyBindings(new listModel());
這里比較容易搞混的是DOM節(jié)點(diǎn)與ViewModel的層次對(duì)應(yīng)關(guān)系。首先,在ul上應(yīng)用 foreach 綁定,也就是每個(gè) li 對(duì)應(yīng)每個(gè) people 子項(xiàng)。這一點(diǎn)對(duì)應(yīng)上了之后,就按照 js 的作用域規(guī)則去理解即可。說到作用域,不得不提 this,正所謂我待this如初戀,this坑我千百遍。這里小茄在官方版本上加了個(gè)remove函數(shù),與官方的removePeople對(duì)應(yīng)起來看就簡(jiǎn)單了。至于$index, $parent這些變量,按字面意思理解即可。
交互類屬性
終于要到重點(diǎn)了,使用ko的最重要原因就是為了處理動(dòng)態(tài)交互的UI展現(xiàn)問題,這里集中介紹一下與表單相關(guān)的一些綁定。
(1) click綁定
語法:data-bind="click: clickHandler",這里的clickHandler函數(shù)可以是任意函數(shù),并不一定要是ViewModel里的函數(shù),只要能引用到即可。關(guān)于click事件有幾點(diǎn)需要留意的:
1. 參數(shù)傳遞,ko默認(rèn)將當(dāng)前組件作為第一個(gè)參數(shù)傳給clickHandler函數(shù),這里要注意當(dāng)前的綁定上下文,比如說在with環(huán)境中,傳回的組件就會(huì)變成with組件而不是你想要的當(dāng)前組件。如果你還需要傳遞event參數(shù),則將event作為第二個(gè)參數(shù)傳入。如果還需要傳入更多的參數(shù),那么就需要使用一個(gè)函數(shù)包裝起來了。如:
<button data-bind="click: function(data, event) { myFunction('param1', 'param2', data, event) }"> Click me </button>
2. 默認(rèn)行為的設(shè)置(比如鏈接)
ko默認(rèn)是禁止默認(rèn)事件行為的,通常我們?yōu)殒溄咏壎c(diǎn)擊事件也不會(huì)是讓其跳轉(zhuǎn)的。不過你如果一定要開啟的話,直接在clickHandler里面return true即可。
3. 冒泡
ko默認(rèn)是允許冒泡的,你可以通過 data-bind="click: clickHandler, clickBubble: false"來設(shè)置click事件不冒泡。
(2)event綁定
ko提供了這個(gè)接口讓用戶自定義綁定事件。關(guān)于參數(shù)傳遞、默認(rèn)行為、冒泡等與click綁定是一樣的,使用案例:
<div> <div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }"> Mouse over me </div> <div data-bind="visible: detailsEnabled"> Details </div> </div> <script type="text/javascript"> var viewModel = { detailsEnabled: ko.observable(false), enableDetails: function() { this.detailsEnabled(true); }, disableDetails: function() { this.detailsEnabled(false); } }; ko.applyBindings(viewModel); </script>
(3)submit綁定
主要用來做一些驗(yàn)證表單的工作。ko會(huì)阻止默認(rèn)的提交表單動(dòng)作,并轉(zhuǎn)入submit綁定的函數(shù)中。后續(xù)需要提交的時(shí)候,在綁定事件中 return true即可。
PS: 為什么不在表單中使用 click 事件來處理呢?因?yàn)?submit 本來就是被設(shè)計(jì)用來處理提交事件的,它還能接受回車一類的提交動(dòng)作,但click則不行。
(4)value 與 textInput 綁定
在輸入框綁定 value 和 textInput 看起來效果差不多,但是更推薦使用 textInput 事件進(jìn)行綁定,因?yàn)?textInput 是新增的專門用來處理輸入事件的。在上一篇文章中可以看到,使用 value 綁定時(shí)(左)輸入之后必須要將焦點(diǎn)從輸入框中移出才會(huì)進(jìn)行更新,而 textInput (右)是馬上進(jìn)行更新的。
雖然,value 綁定也可以通過設(shè)置 data-bind="{value: price, valueUpdate: 'afterkeydown'}" 實(shí)現(xiàn)與 textInput 一樣的效果,但是這個(gè)在瀏覽器中的兼容性并不如 textInput 好。
(5)options綁定(selectedOptions)
在下拉列表中可使用 options 來綁定子項(xiàng)的值,子項(xiàng)既可以是字符串,也可以是 js 對(duì)象。上一篇(【Knockoutjs 學(xué)習(xí)體驗(yàn)之旅】(1)ko初體驗(yàn))中展示的是字符串,這次就來傳個(gè)對(duì)象:
代碼:
<p>Your country: <select data-bind="options: availableCountries, optionsText: 'countryName', value: selectedCountry, optionsCaption: 'Choose...'"></select> </p> <div data-bind="visible: selectedCountry"> <!-- Appears when you select something --> You have chosen a country with population <span data-bind="text: selectedCountry() ? selectedCountry().countryPopulation : 'unknown'"></span>. </div> <script type="text/javascript"> // Constructor for an object with two properties var Country = function(name, population) { this.countryName = name; this.countryPopulation = population; }; var viewModel = { availableCountries: ko.observableArray([ new Country("UK", 65000000), new Country("USA", 320000000), new Country("Sweden", 29000000) ]), selectedCountry: ko.observable() // Nothing selected by default }; ko.applyBindings(viewModel); </script>
這里使用了option來綁定列表框的選項(xiàng),使用value綁定選中項(xiàng)目。由于選項(xiàng)是 js 對(duì)象,所以要用一個(gè) optionText 來指定在列表框中的展示。optionCaption是指無選中任何項(xiàng)目時(shí)候的默認(rèn)顯示值。如果我們?cè)O(shè)定的是多選列表框的話,那么就不能用 value 來綁定選中項(xiàng)目了,這個(gè)時(shí)候要用到 selectOptions來綁定選中項(xiàng)目。
(6)其他綁定:enable/disable, hasFocus , checked , uniqueName。
這些事件用起來非常簡(jiǎn)單,就不具體介紹了。最后一個(gè) uniqueName 是用來設(shè)置表單控件的唯一 name 屬性的,表單中提交到后臺(tái)時(shí),沒有設(shè)置 name 屬性的值時(shí)不會(huì)被提交到后臺(tái)的,所以就有了這么個(gè)綁定功能。官網(wǎng)中關(guān)于 hasFoucus 還有個(gè)比較常用的效果:
Name:
Name: Bert Bertington
Click the name to edit it; click elsewhere to apply changes.
點(diǎn)擊上面的姓名就可以變成可編輯狀態(tài),失去焦點(diǎn)后又變成普通文字,這種效果用ko實(shí)現(xiàn)起來相當(dāng)簡(jiǎn)單。
總結(jié)
本篇主要簡(jiǎn)單介紹了knockoutjs中各種綁定的使用方法,使用這些綁定方法的組合就能簡(jiǎn)單地做好一個(gè)需要較多動(dòng)態(tài)交互的UI頁面。使用這些方法比較重要的一點(diǎn)就是要記住綁定的都是函數(shù)對(duì)象,所以可以直接在HTML里面進(jìn)行操作,這樣的話有時(shí)候 js 代碼結(jié)構(gòu)可以更簡(jiǎn)單。
官方教程: http://knockoutjs.com/documentation/introduction.html
- Knockoutjs 學(xué)習(xí)系列(一)ko初體驗(yàn)
- WebApi+Bootstrap+KnockoutJs打造單頁面程序
- KnockoutJs快速入門教程
- BootstrapTable與KnockoutJS相結(jié)合實(shí)現(xiàn)增刪改查功能【二】
- BootstrapTable與KnockoutJS相結(jié)合實(shí)現(xiàn)增刪改查功能【一】
- Bootstrap與KnockoutJs相結(jié)合實(shí)現(xiàn)分頁效果實(shí)例詳解
- Knockoutjs快速入門(經(jīng)典)
- knockoutjs動(dòng)態(tài)加載外部的file作為component中的template數(shù)據(jù)源的實(shí)現(xiàn)方法
相關(guān)文章
利用babel將es6語法轉(zhuǎn)es5的簡(jiǎn)單示例
Babel是一個(gè)廣泛使用的轉(zhuǎn)碼器,babel可以將ES6代碼完美地轉(zhuǎn)換為ES5代碼,所以下面這篇文章就來給大家詳細(xì)介紹了關(guān)于利用babel將es6語法轉(zhuǎn)es5的相關(guān)資料,文章通過示例介紹的非常詳細(xì),需要的朋友可以參考下。2017-12-12JavaScript注冊(cè)時(shí)密碼強(qiáng)度校驗(yàn)代碼
這篇文章主要為大家詳細(xì)介紹了JavaScript注冊(cè)時(shí)密碼強(qiáng)度校驗(yàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06原生js實(shí)現(xiàn)移動(dòng)小球(碰撞檢測(cè))
這篇文章主要介紹了原生js實(shí)現(xiàn)會(huì)動(dòng)的小球,碰撞檢測(cè)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12JS無縫滾動(dòng)效果實(shí)現(xiàn)方法分析
這篇文章主要介紹了JS無縫滾動(dòng)效果實(shí)現(xiàn)方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了無縫滾動(dòng)的原理、實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-12-12JavaScript人臉識(shí)別技術(shù)及臉部識(shí)別JavaScript類庫Tracking.js
人臉識(shí)別的JavaScript程序包是Face Detection,它是由Jay Salvat和Liu Liu開發(fā)的。它是一個(gè)標(biāo)準(zhǔn)的jQuery插件,通過對(duì)提供的圖片進(jìn)行分析,返回所有找到的臉部圖像的坐標(biāo),感興趣的朋友跟著小編一起學(xué)習(xí)js人臉識(shí)別技術(shù)及臉部識(shí)別JavaScript類庫Tracking.js吧2015-09-09JavaScript循環(huán)鏈表實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于JavaScript循環(huán)鏈表實(shí)現(xiàn)的相關(guān)資料,循環(huán)鏈表和單向鏈表很相似,唯一的區(qū)別是循環(huán)鏈表的尾節(jié)點(diǎn)是指向頭節(jié)點(diǎn)的,需要的朋友可以參考下2023-07-07