1、作者源码
实现一个简单的双向绑定
<!DOCTYPE html>
<html>
<head>
<title>ideal</title>
<meta charset="utf-8">
</head>
<body>
<div id="test">
<p>{{msg}}</p>
<p>{{msg}}</p>
<p>{{msg}}</p>
<p>{{what}}</p>
<p>{{hey}}</p>
</div>
<script>
var bindingMark = 'data-element-binding' // 元素绑定标志
function Element (id, initData) {
var self = this,
el = self.el = document.getElementById(id)
bindings = {} // 内部副本
data = self.data = {} // 外部接口
content = el.innerHTML.replace(/\{\{(.*)\}\}/g, markToken) // 匹配双括号,添加标志位,并将属性拷贝到内部副本
el.innerHTML = content // 用替换后的标签内容,生成新的dom树
for (var variable in bindings) {
bind(variable) // 数据绑定方法
}
if (initData) {
for (var variable in initData) { // 进行赋值,只用这样才能用defineProperty监听属性变化
data[variable] = initData[variable]
}
}
function markToken (match, variable) {
bindings[variable] = {}
return '<span ' + bindingMark + '="' + variable +'"></span>'
}
function bind (variable) {
bindings[variable].els = el.querySelectorAll('[' + bindingMark + '="' + variable + '"]')
;[].forEach.call(bindings[variable].els, function (e) {
e.removeAttribute(bindingMark)
}) // 获取页面数据绑定元素,并移除标志位
Object.defineProperty(data, variable, { // 实行双向布局绑定
set: function (newVal) {
[].forEach.call(bindings[variable].els, function (e) {
bindings[variable].value = e.textContent = newVal
})
},
get: function () {
return bindings[variable].value
}
})
}
}
var app = new Element('test', {
msg: 'hello'
})
</script>
</body>
</html>
···