mvvm雙向綁定機(jī)制的原理和實(shí)現(xiàn)代碼(推薦)
mvvm框架的雙向綁定,即當(dāng)對(duì)象改變時(shí),自動(dòng)改變相關(guān)的dom元素的值,反之,當(dāng)dom元素改變時(shí),能自動(dòng)更新對(duì)象的值,當(dāng)然dom元素一般是指可輸出的input元素。
1. 首先實(shí)現(xiàn)單向綁定,在指定對(duì)象的屬性值發(fā)生改變時(shí)觸發(fā)callback函數(shù)。
2. 單向綁定可采用ES5新增的defineProperty實(shí)現(xiàn)(或defineProperties),用了ES5注定就不支持IE9以下了,為了防止遞歸死循環(huán)問題,原有屬性需要剪切到一個(gè)私有屬性中保存。
3. 循環(huán)調(diào)用defineProperty定義閉包時(shí)產(chǎn)生作用域的問題,為解決作用域變量對(duì)象的值會(huì)取到最后一次運(yùn)行值問題,多定義一層立即調(diào)用的閉包函數(shù)將值傳入。
4. 我們定義getFN和setFN函數(shù)用于在屬性get和set的時(shí)候觸發(fā),它的功能是對(duì)私有屬性__private的讀寫并觸發(fā)回調(diào)函數(shù)通知UI層更新界面。
5.單向綁定實(shí)現(xiàn)完成后,實(shí)現(xiàn)反向的綁定,即UI層onchange之后觸發(fā)更新數(shù)據(jù),這個(gè)相對(duì)比較容易,在dom中通過自定義屬性bindKey關(guān)聯(lián)model的值變化,監(jiān)聽使用oninput事件,相比onchange的好處是可以實(shí)時(shí)變化不用等失焦,而且對(duì)右鍵粘貼、菜單粘貼,拖動(dòng)文字進(jìn)文本框等方式都可以觸發(fā),完全無死角,缺點(diǎn)是只支持IE9以上,但是在IE9以下有等價(jià)的onpropertychange可以用還是能兼容的。
6.總結(jié),雙向綁定的原理并不復(fù)雜,整體代碼不超過50行,非常精簡(jiǎn),不過還是有一些技術(shù)含量,下面是完整的代碼,如果不想使用龐大的框架,可以用一下。ie9以下是不支持的,如要支持ie9以下可以使用avalon,它用vbs做了get,set存取器的封裝,這點(diǎn)還是比較強(qiáng)大的。
html:
<div id="container"> <p> name:<input type="text" bindkey="userName"> </p> <p> age:<input type="text" bindkey="age"> </p> <div>
js:
<script type="text/javascript"> window.Model={ userName:"windy", age:34, skill:["javascript","html","css","jquery","node"], } function bindingModel(model,changeCallback){ var propertiesMap={}; model.__private={}; function getFn(name){ var result=this.__private[name] console.log("get value:"+name+"="+ result); return result; }; function setFn(name,val){ if(this.__private[name]!=val){ console.log("set value:"+name+"="+val); this.__private[name]=val; if(changeCallback){ changeCallback(name,val); } } }; for(elem in model){ if(model.hasOwnProperty(elem) && elem!="__private" && typeof(model[elem])!="function"){ (function(propName,propValue){ model.__private[propName]=propValue;// init value propertiesMap[propName]={ get:function(){ return getFn.call(this,propName)}, set:function(v){ return setFn.call(this,propName,v)}, //value:model[elem], //writable: true, enumerable: true, configurable: true } })(elem,model[elem]); } } Object.defineProperties(model,propertiesMap) } function bindingBoth(model,dom){ dom.find("[bindkey]").each(function(item){ var key=$(this).attr("bindkey"); $(this).val(model[key]); $(this).bind("input",function(){ model[key]=$(this).val(); }) }); bindingModel(model,function(name,val){ var el=dom.find("[bindkey="+name+"]"); if(el.val()!=val){ el.val(val); } }); } bindingBoth(window.Model,$("#container")) </script>
以上這篇mvvm雙向綁定機(jī)制的原理和實(shí)現(xiàn)代碼(推薦)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
javascript Slip.js實(shí)現(xiàn)整屏滑動(dòng)的手機(jī)網(wǎng)頁(yè)
Slip.js能做什么?Slip.js可以讓你的手機(jī)網(wǎng)站像原生手機(jī)軟件一樣慣性滾動(dòng),手觸圖片輪換等等,對(duì)Slip.js感興趣的小伙伴們可以參考一下2015-11-11JavaScript Window瀏覽器對(duì)象模型原理解析
這篇文章主要介紹了JavaScript Window瀏覽器對(duì)象模型,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05JavaScript極簡(jiǎn)入門教程(一):基礎(chǔ)篇
這篇文章主要介紹了JavaScript極簡(jiǎn)入門教程(一):基礎(chǔ)篇,本文講解了JavaScript的基礎(chǔ)語(yǔ)法、操作符、運(yùn)算符等內(nèi)容,需要的朋友可以參考下2014-10-10js使用html()或text()方法獲取設(shè)置p標(biāo)簽的顯示的值
html()方法可以用來讀取或者設(shè)置某個(gè)元素中的HTML內(nèi)容,text()方法可以用來讀取或者沒置某個(gè)元素中的文本內(nèi)容2014-08-08JS生態(tài)系統(tǒng)加速一次一庫(kù)PostCSS SVGO的重構(gòu)源碼和性能優(yōu)化探索
這篇文章主要介紹了JS生態(tài)系統(tǒng)加速一次一庫(kù)PostCSS SVGO的重構(gòu)源碼和性能優(yōu)化探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01