前言
自从Angular火了一把以后,数据与视图的双向绑定,已经成为了现代前端框架的标配,本系列将会探讨目前主流前端框架的双向绑定实现原理与代码实现。
目前,对于双向绑定的实现,主要分为三个流派,Angular使用的是脏刷新,Vue使用的是Getter/Setter,而React 则是在脏刷新的的基础上,增加了虚拟dom树与实际dom树改变的刷新机制。
基本原理
遍历Dom树,解析Dom树上的字符串,当找到可以替换成model变量的字符串,替换成model的数据,同时,检测model的数据变化,数据变化的时候,触发渲染动作,对Dom进行重新渲染。对于Angular 与 Vue 主要的区别在数据变动检测部分。Vue利用object的getter/setter方法作为渲染的钩子产生渲染事件,而Angular则主动调用$digest激活数据脏刷新,React在脏刷新的基础上,放弃对Dom进行比较操作,直接从内存中比较出变化后,一次性生成到对应的Dom结构上。
实现目标
围绕上述三个双向绑定模式,我们将会用相同的案例来展现双向绑定的效果。
html
<div id="demo1" class="section">
Hello <span class='{{css}}'>{{name}}</span>!
</div>
<div id='demo2' class='section'>
<label><span>name:</span>
<input name='name'>
</label>
<br>
<label><span>password:</span>
<input name='password'>
</label>
<pre>{
name: {{name}},
passowrd: {{password}}
}</pre>
</div>
javascript
var demo1 = mvvc('#demo1', {
model: {
name: 'world',
css: 'green'
}
});
var demo2 = mvvm('#demo2', {
type: 'form', // 同步
model: {
name: '',
password: ''
}
})
准备工作
在分享各个双向数据绑定框架,抽取相同的逻辑部分进行分析。
1.遍历Dom元素,提取属性与文本
function renderDom(dom, model) {
each(dom.attributes, function() {
render(this, model);
});
each(dom.childNodes, function () {
if (this.nodeType === 1) {
return renderDom(this, model);
}
render(this, model);
})
}
2.提取元素里面被提取的可变量{{name}}
和{{css}}
,并替换成model的变量后重新渲染页面。
function render(node, model) {
var self = this;
var attr = node.textContent.split(start);
if (!attr.length) return;
var ret = '';
for (var i = 0; i < attr.length; i++) {
var two = attr[i].split(end);
if (two.length == 1) {
ret += attr[i];
} else {
ret = model[two[0] + two[1]];
}
node.textContent = ret;
}
}
3.成功实现model的数据渲染
效果图代码参考:
http://codepen.io/youyudehexie/pen/MKbXvM
网友评论