Неужели это невозможно, если использовать функцию se t defineProperty для фактической установки значения свойства?

Я хочу реализовать двустороннее связывание данных (как в Angular или Vue) с использованием ванильного JavaScript.

Представление для моделирования части, которую я могу использовать, добавляет входной слушатель события, и модель для просмотра части, я хочу использовать функцию set Object.defineProperty.

В функции set defineProperty мне нужно изменить значение представления и установить значение свойства, но это вызовет "Превышен максимальный размер стека вызовов", потому что 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>

2 ответа

Решение

Ответить на ваш вопрос - нет. Если у вас есть сеттер, вы не можете развернуться и установить значение без зацикливания. Альтернатива состоит в том, чтобы иметь частную собственность на объекте, который только get() а также set() методы будут взаимодействовать с. Внешний мир будет использовать только те свойства, которые имеют геттеры / сеттеры.

Не уверен, что это отличный способ реализации связывания, но это способ создать видимость использования установщика для установки свойства:

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)

В функции установки мне нужно установить значение свойства, но оно вызовет "Превышен максимальный размер стека вызовов", потому что значение установленного свойства будет рекурсивно выполняться снова и снова.

Да. Не делай этого. Настройка input.value достаточно, получатель уже сообщит новое значение.

когда я console.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);
Другие вопросы по тегам