我想使用vanilla JavaScript实现双向数据绑定(如Angular或Vue)。
模型部分的视图我可以使用添加输入事件监听器, 以及查看部分的模型,我想使用Object.defineProperty的set函数。
在defineProperty的set函数中,我需要更改视图的值并设置属性值,但是会导致“超出最大调用堆栈大小”,
因为set property value
将一次又一次地递归运行。
现在的问题是:有没有办法可以同时使用set函数并设置其属性值?
现在我的代码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>2 Way Data Binding</title>
</head>
<body>
text: <input id="text" class="text" type="text">
</body>
<script type="text/javascript">
var input = document.querySelector("#text");
var data = {};
Object.defineProperty(data, "text", {
get: function(){
return input.value
},
set: function(newValue){
input.value = newValue;
// data.text = newValue; // <------ this is the problem
}
})
input.input = function(){
data.text = data.text;
}
</script>
</html>
答案 0 :(得分:1)
回答你的问题 - 不。如果你有一个setter,你就可以转身并设置值而不需要循环。另一种方法是在对象上拥有一个私有属性,只有get()
和set()
方法才能与之交互。外部世界将仅使用具有getter / setter的属性。
不确定这是否是实现绑定的好方法,但它是一种使用setter来设置属性的方法:
const data = {
// _text is the source of truth
_text: "some text",
get text() {
return this._text
},
set text(newValue) {
input.value = newValue;
this._text = newValue;
}
};
const input = {
value: data.text
}
// original value
console.log(data.text)
console.log(input.value)
// change it
data.text = "other text"
console.log(data.text)
console.log(input.value)
&#13;
答案 1 :(得分:0)
在setter函数中我需要设置属性值,但是它会导致&#34;超出最大调用堆栈大小&#34;,因为set属性值会一次又一次地递归运行。
是。不要这样做。设置input.value
就足够了,getter已经报告了新值。
当我在console.log中我的视图模型(在我上面的代码中是数据)时,结果是{}(一个空对象)。所以说,如果我想迭代我的视图模型,那就无法完成。
这是一个非常不同的问题。通过制作属性enumerable:
可以轻松解决这个问题var input = document.querySelector("#text");
var data = {};
Object.defineProperty(data, "text", {
enumerable: true,
get: function(){
return input.value
},
set: function(newValue){
input.value = newValue;
}
});
console.log(data);