原生MVVM双向绑定

54 阅读1分钟
<!DOCTYPE html>
<html>
<head>
  <title>MVVM with Native JS</title>
</head>
<body>
  <!-- 输入框,用户输入文本 -->
  <input id="inputField" type="text">
  <!-- 显示绑定后的输出文本 -->
  <p id="outputText"></p>

  <script>
    // 定义一个观察者类,用于管理订阅者和数据变化通知
    class Observer {
      constructor() {
        // 存储订阅者的数组
        this.subscribers = [];
      }

      // 添加订阅者
      subscribe(callback) {
        this.subscribers.push(callback);
      }

      // 通知所有订阅者,数据发生了变化
      notify(data) {
        this.subscribers.forEach(subscriber => {
          subscriber(data);
        });
      }
    }

    // 定义一个视图模型类,管理数据和数据变化的观察者
    class ViewModel {
      constructor() {
        // 数据对象,包含一个输入字段的值
        this.data = {
          inputValue: ''
        };
        // 创建一个观察者实例,用于监听输入字段的变化
        this.inputObserver = new Observer();
      }

      // 设置输入字段的值,并通知观察者数据变化
      setInputValue(value) {
        this.data.inputValue = value;
        this.inputObserver.notify(value);
      }

      // 将一个观察者回调函数绑定到输入字段的变化上
      bindInput(observerCallback) {
        this.inputObserver.subscribe(observerCallback);
      }
    }

    // 定义一个绑定器类,用于建立输入字段和输出元素的双向绑定
    class Binder {
      constructor(viewModel) {
        this.viewModel = viewModel;
        // 获取输入字段和输出元素的 DOM 元素
        this.inputField = document.getElementById('inputField');
        this.outputText = document.getElementById('outputText');

        // 建立输入字段的变化监听,将变化通知给视图模型
        this.bindInput();
        // 将视图模型的数据绑定到输出元素上
        this.bindOutput();
      }

      // 监听输入字段的变化,将变化通知给视图模型
      bindInput() {
        this.inputField.addEventListener('input', (event) => {
          const newValue = event.target.value;
          // 更新视图模型中的输入字段值
          this.viewModel.setInputValue(newValue);
        });
      }

      // 将视图模型中的数据绑定到输出元素上,实现双向绑定
      bindOutput() {
        this.viewModel.bindInput((data) => {
          // 将视图模型的输入字段值显示在输出元素中
          this.outputText.textContent = data;
        });
      }
    }

    // 创建一个视图模型实例
    const viewModel = new ViewModel();
    // 创建一个绑定器实例,将视图模型和视图连接起来
    const binder = new Binder(viewModel);
  </script>
</body>
</html>