mvvm框架的双向绑定,即当对象改变时,自动改变相关的dom元素的值,反之,当dom元素改变时,能自动更新对象的值,当然dom元素一般是指可输出的input元素。
1. 首先实现单向绑定,在指定对象的属性值发生改变时触发callback函数。
2. 单向绑定可采用ES5新增的defineProperty实现(或defineProperties),用了ES5注定就不支持IE9以下了,为了防止递归死循环问题,原有属性需要剪切到一个私有属性中保存。
3. 循环调用defineProperty定义闭包时产生作用域的问题,为解决作用域变量对象的值会取到最后一次运行值问题,多定义一层立即调用的闭包函数将值传入。
4. 我们定义getFN和setFN函数用于在属性get和set的时候触发,它的功能是对私有属性__private的读写并触发回调函数通知UI层更新界面。
5.单向绑定实现完成后,实现反向的绑定,即UI层onchange之后触发更新数据,这个相对比较容易,在dom中通过自定义属性bindKey关联model的值变化,监听使用oninput事件,相比onchange的好处是可以实时变化不用等失焦,而且对右键粘贴、菜单粘贴,拖动文字进文本框等方式都可以触发,完全无死角,缺点是只支持IE9以上,但是在IE9以下有等价的onpropertychange可以用还是能兼容的。
6.总结,双向绑定的原理并不复杂,整体代码不超过50行,非常精简,不过还是有一些技术含量,下面是完整的代码,如果不想使用庞大的框架,可以用一下。ie9以下是不支持的,如要支持ie9以下可以使用avalon,它用vbs做了get,set存取器的封装,这点还是比较强大的。
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双向绑定机制的原理和实现代码(推荐)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持phpstudy。
本文地址:https://www.stayed.cn/item/8484
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我