The two-way binding of the mvvm framework, that is, when the object changes, the value of the relevant dom element will be automatically changed. On the contrary, when the dom element changes, the value of the object can be automatically updated. Of course, the dom element generally refers to the output input element.
1. First, one-way binding is implemented, and the callback function is triggered when the property value of the specified object changes.
2. One-way binding can use the newly added defineProperty implementation (or defineProperties) in ES5. If ES5 is used, it is destined to not support IE9. In order to prevent the recursive dead loop problem, the original attribute needs to be cut into a private attribute to save.
3. The problem of scope arising from calling defineProperty to define closures in loop. In order to solve the problem that the value of the scope variable object will be retrieved to the last run value, define an additional layer of closure function called immediately to pass the value in.
4. We define getFN and setFN functions to trigger when properties get and set. Its function is to read and write the private property __private and trigger the callback function to notify the UI layer to update the interface.
5. After the one-way binding is implemented, reverse binding is implemented, that is, the UI layer onchange triggers the update data. This is relatively easy. In the dom, the value change of the model is associated with the custom property bindKey, and the oninput event is monitored. Compared with onchange, the advantage of it is that it can change in real time without waiting for out of focus. Moreover, it can be triggered by right-click pasting, menu pasting, dragging text into text boxes, etc., with no blind spots at all. The disadvantage is that it only supports IE9 or above, but there are equivalent onpropertychange below IE9 and can be used or compatible.
6. Summary: The principle of two-way binding is not complicated. The overall code does not exceed 50 lines, which is very simple. However, there is still some technical content. The following is the complete code. If you don’t want to use a huge framework, you can use it. The following ie9 is not supported. If you want to support the following ie9, you can use avalon. It uses vbs to encapsulate the get and set accessor, which is quite powerful.
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>The above principles and implementation code of the mvvm two-way binding mechanism (recommended) are all the content I share with you. I hope you can give you a reference and I hope you can support Wulin.com more.