这是否不可能使用定义属性设置函数来实际设置属性值



我想使用vanilla JavaScript实现双向数据绑定(如在Angular或Vue中(。

模型部分 I 的视图可以使用添加输入事件侦听器,和模型查看部分,我想使用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>

回答你的问题——不。如果你有一个二传手,你不能转身设置值而不循环。另一种方法是在对象上具有私有属性,只有 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)

在 setter 函数中,我需要设置属性值,但它会导致"超出最大调用堆栈大小",因为设置的属性值会一次又一次地递归运行。

是的。别这样。设置input.value就足够了,getter 已经报告了新值。

当我控制台时.log我的视图模型(在上面的代码中是数据(,结果是{}(一个空对象(。所以说,如果我想迭代我的视图模型,那是做不到的。

嗯,这是一个非常不同的问题。这可以通过使属性可枚举来轻松解决:

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);

最新更新