今天来说一下Javascript是如何实现数据的双向绑定,由于是第一次写文章因此是借鉴了一下别人的文章。根据别人的文章来谈一些本身的理解,废话很少说直接开始讲解。javascript
首先数据双向绑定你们必定都不陌生(如angular,vue等),那么它的结构大体以下html
<input q-value="value" type="text" id="input">
<div q-text="value" id="el"></div>
复制代码
这跟vue的写法很像这是比较老的实现方式,有点像观察者编程模式,主要思路是经过在数据对象上定义get和set方法(固然还有其它方法),调用时手动调用get或set数据,改变数据后出发UI层的渲染操做;以视图驱动数据变化的场景主要应用与input、select、textarea等元素,当UI层变化时,经过监听dom的change,keypress,keyup等事件来出发事件改变数据层的数据。整个过程均经过函数调用完成。 先上一段代码vue
var elems = [document.getElementById('el'), document.getElementById('input')];
复制代码
总体思路是先取到标签,而后把取到的标签放到一个数组里java
var data = {
value: 'hello!'
};
复制代码
以后定义一个初始化的值数组data里面value的值为hellonode
var command = {
text: function(str){
this.innerHTML = str;
},
value: function(str){
this.setAttribute('value', str);
}
};
复制代码
text定义文本得内容 value输入的内容以后经过setAttribute() 方法给输入框添加指定的文本内容 定义完以后基础的部分也就作好了以后是须要进行逻辑的编写编程
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));
}
}
}
}
复制代码
首先须要循环节点首先定义一个空数组elem.command = []用来存取改变的值, 以后须要循环获取指定字符首次出现的位置elem.attributes.length就是这个东西而后作判断调用指令,这里可使用数据改变检测数组
command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
elem.command.push(attr.nodeName.slice(2));
复制代码
以后能够设置扫描执行来改变视图的显示bash
function mvSet(key, value){
data[key] = value;
scan();
}
复制代码
而后经过数据绑定监听来实现数据的绑定效果dom
elems[1].addEventListener('keyup', function(e){
mvSet('value', e.target.value);
}, false);
复制代码
addEventListener方法用于向指定元素添加事件句柄函数
target可返回事件目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。
最后一步就是设置时间来更新视图的显示
setTimeout(function(){
mvSet('value', data.value)
},1000)
复制代码
这里绑定了刚才上面设置的数组的值
下面帖一下总体的代码
<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>
复制代码
这样就作到了javascript的双向数据绑定,测试了一下绑定的数据仍是不能改变的只能作到视图层的改变,以后我会进一步的研究双向绑定数据是如何改变的原理。
参考文章转自http://www.jb51.net/article/107917.html
若有解释上的错误还望各位提出来我会一一改正
通过3天的研究成果就是这么多由于本人是第一次发文章内心仍是有点小紧张的但愿各位多多包涵,谢谢。