前端数据的双向绑定方法
前端的视图层和数据层有时需要实现双向绑定(two-way-binding),例如mvvm框架,数据驱动视图,视图状态机等,研究了几个目前主流的数据双向绑定框架,总结了下。目前实现数据双向绑定主要有以下三种。
1、手动绑定
比较老的实现方式,有点像观察者编程模式,主要思路是通过在数据对象上定义get和set方法(当然还有其它方法),调用时手动调用get或set数据,改变数据后出发UI层的渲染操作;以视图驱动数据变化的场景主要应用与input、select、textarea等元素,当UI层变化时,通过监听dom的change,keypress,keyup等事件来出发事件改变数据层的数据。整个过程均通过函数调用完成。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>data-binding-method-set</title></head><body> <input q-value="value" type="text" id="input"> <div q-text="value" id="el"></div> <script> var elems = [document.getElementById('el'), document.getElementById('input')]; var data = { value: 'hello!' }; var command = { text: function(str){ this.innerHTML = str; }, value: function(str){ this.setAttribute('value', str); } }; var scan = function(){ /** * 扫描带指令的节点属性 */ for(var i = 0, len = elems.length; i < len; i++){ var elem = elems[i]; elem.command = []; for(var j = 0, len1 = elem.attributes.length; j < len1; j++){ var attr = elem.attributes[j]; if(attr.nodeName.indexOf('q-') >= 0){ /** * 调用属性指令,这里可以使用数据改变检测 */ command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]); elem.command.push(attr.nodeName.slice(2)); } } } } /** * 设置数据后扫描 */ function mvSet(key, value){ data[key] = value; scan(); } /** * 数据绑定监听 */ elems[1].addEventListener('keyup', function(e){ mvSet('value', e.target.value); }, false); scan(); /** * 改变数据更新视图 */ setTimeout(function(){ mvSet('value', 'fuck'); },1000) </script></body></html>
2、脏检查机制
以典型的mvvm框架angularjs为代表,angular通过检查脏数据来进行UI层的操作更新。关于angular的脏检测,有几点需要了解些: - 脏检测机制并不是使用定时检测。 - 脏检测的时机是在数据发生变化时进行。 - angular对常用的dom事件,xhr事件等做了封装, 在里面触发进入angular的digest流程。 - 在digest流程里面, 会从rootscope开始遍历, 检查所有的watcher。 (关于angular的具体设计可以看其他文档,这里只讨论数据绑定),那我们看下脏检测该如何去做:主要是通过设置的数据来需找与该数据相关的所有元素,然后再比较数据变化,如果变化则进行指令操作
新闻热点
疑难解答
图片精选