实现数据的双向绑定最直接的方式就是PubSub模式。
(1)当model发生变化时,触发Model change事件,然后通过相应事件处理函数更新界面。--'model-update-event'
(2)当界面更新时,触发UI change事件,然后通过相应事件处理函数更新Model,以及绑定在Model上的其他界面控件。--'ui-update-event'
对于所有支持双向绑定的页面控件来说,当控件的'值'发生变化时,会触发'ui-update-event'事件。(这里只处理包含't-binding'属性的控件)。
当Model订阅了(监听)'ui-update-event',相应的界面改动会更新Model。
大致的原理为:
function DataBinder(){ //发布/订阅封装 var pubSub={ handlers:{}, on:function(event,callback){ if(!this.handlers[event]){ this.handlers[event]=[]; } this.handlers[event].push(callback); }, publish:function(event){ var handler=this.handlers[event]; if(handler){ for(var i=0;i<handler.length;i++){ handler[i](); } } } }; changeHandler=fucntion(e){ var target=e.target||e.srcElement; var prop_name=event.getAttribute('t-binding'); if(prop_name && prop_name!==''){ pubSub.publish('ui-update-event',prop_name,target.value); }; }; //监听事件变化(这里监听keyup和change事件),并代理到pubSub上。 if(document.addEventListener){ document.addEventListener('keyup',changeHandler,false); document.addEventListener('change',changeHandler,false); }else{ //兼容ie8 document.attachEvent('keyup',changeHandler); document.attarEvent('change',changeHandler); }; //pubSub将变化传播到所有绑定元素上。 pubSub.on('model-update-event',function(propName,propValue){ var eles=document.querySelectorAll('[t-binding="'+propName+'"]'); for(var i=0;i<eles.length;i++){ var eleType=eles[i].tagName.toLowerCase(); //更新UI界面上元素的内容 if(eleType=='input' || eleType=='textarea' || eleType=='select' ){ eles[i].value=propValue; }else{ eles[i].innerHTML=propValue; } } }