现在vue如日中天,于是也凑个热闹学习一下。在学习vue的双向数据绑定的过程中,发现一个非常诡异的现象,百思不得其解,还望哪位大侠指点一下。
先看如下代码(熟悉vue的应该很好懂):
<!DOCTYPE html>
<html>
<head>
<title>ideal</title>
<meta charset="utf-8">
</head>
<body>
<input class="test" type="text" name="asd" onkeyup="handleChange()" v-model="hey">
<input class="test" type="" name="" onkeyup="handleChange()" v-model="msg">
<script>
var bindingMark = 'data-element-binding'
function Element(classa, initData) {
var self = this,
el = self.el = document.getElementsByClassName(classa),
bindings = {}
data = self.data = {}
for (var i = 0; i < el.length; i++) {
//content = el[i].outerHTML.replace(/v-model=\"(.*)\"/g, markToken);
content = el[i].outerHTML.replace(/v-model=\"(.*)\"/g, function(match, variable) {
bindings[variable] = {}
return bindingMark + '="' + variable + '"'
});
el[i].outerHTML = content
}
for (var variable in bindings) {
//bind(variable);
bindings[variable].els = document.querySelectorAll('[' + bindingMark + '="' + variable + '"]')
Object.defineProperty(data, variable, {
set: function (newVal) {
[].forEach.call(bindings[variable].els, function (e) {
bindings[variable].value = e.value = newVal
})
},
get: function () {
return bindings[variable].value
}
})
}
if (initData) {
for (var variable in initData) {
data[variable] = initData[variable]
}
}
function markToken(match, variable) {
bindings[variable] = {}
return bindingMark + '="' + variable + '"'
}
function bind(variable) {
bindings[variable].els = document.querySelectorAll('[' + bindingMark + '="' + variable + '"]')
Object.defineProperty(data, variable, {
set: function (newVal) {
[].forEach.call(bindings[variable].els, function (e) {
//textContent改为input的value
bindings[variable].value = e.value = newVal
})
},
get: function () {
return bindings[variable].value
}
})
}
}
var app = new Element('test', {
msg: 'hello',
hey: 'aaa'
})
function handleChange(e) {
e = e || window.event
var key = e.target.outerHTML.match(/data-element-binding=\"(.*)\"/)[1];
data[key] = e.target.value
console.log(data.hey, data.msg);
}
</script>
</body>
</html>
上面这段代码,原来的代码中涉及到两个只调用了一次的函数:markToken和bind,于是我将其合并到调用的地方,结果诡异的事情出现了:原来互不影响的两个input的值,现在如果改变第二个input的值竟然会影响第一个input的值!进一步测试后发现,这与将markToken函数合并无关,而只与将bind函数合并有关。
如果在Chrome控制台查看data对象的值发现,改之前其两个属性(data.hey、data.msg)的值不同,改之后这两个属性的值相同:
问题出在哪里?
这里,闭包啊,set和get里variable都指向一个了