前言
自從Angular火了一把以后,數(shù)據(jù)與視圖的雙向綁定,已經(jīng)成為了現(xiàn)代前端框架的標(biāo)配,本系列將會(huì)探討目前主流前端框架的雙向綁定實(shí)現(xiàn)原理與代碼實(shí)現(xiàn)。
目前,對(duì)于雙向綁定的實(shí)現(xiàn),主要分為三個(gè)流派,Angular使用的是臟刷新,Vue使用的是Getter/Setter,而React 則是在臟刷新的的基礎(chǔ)上,增加了虛擬dom樹(shù)與實(shí)際dom樹(shù)改變的刷新機(jī)制。
基本原理
遍歷Dom樹(shù),解析Dom樹(shù)上的字符串,當(dāng)找到可以替換成model變量的字符串,替換成model的數(shù)據(jù),同時(shí),檢測(cè)model的數(shù)據(jù)變化,數(shù)據(jù)變化的時(shí)候,觸發(fā)渲染動(dòng)作,對(duì)Dom進(jìn)行重新渲染。對(duì)于Angular 與 Vue 主要的區(qū)別在數(shù)據(jù)變動(dòng)檢測(cè)部分。Vue利用object的getter/setter方法作為渲染的鉤子產(chǎn)生渲染事件,而Angular則主動(dòng)調(diào)用$digest激活數(shù)據(jù)臟刷新,React在臟刷新的基礎(chǔ)上,放棄對(duì)Dom進(jìn)行比較操作,直接從內(nèi)存中比較出變化后,一次性生成到對(duì)應(yīng)的Dom結(jié)構(gòu)上。
實(shí)現(xiàn)目標(biāo)
圍繞上述三個(gè)雙向綁定模式,我們將會(huì)用相同的案例來(lái)展現(xiàn)雙向綁定的效果。
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: ''
}
})
準(zhǔn)備工作
在分享各個(gè)雙向數(shù)據(jù)綁定框架,抽取相同的邏輯部分進(jìn)行分析。
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的變量后重新渲染頁(yè)面。
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.成功實(shí)現(xiàn)model的數(shù)據(jù)渲染

代碼參考:
http://codepen.io/youyudehexie/pen/MKbXvM