学习手写v-model

<body>

  <div id="app">
    <div>
      <span>用户</span>
      <input type="text" v-model="username" placeholder="用户" />
      <span>密码</span>
      <input type="text" v-model="password" placeholder="密码" />
      <span>手机</span>
      <input type="text" v-model="phone" placeholder="手机" />
    </div>
    <div>
      <span>用户: <span>{{ username }}</span></span>
    </div>
    <div>
      <span>密码: <span>{{ password }}</span></span>
    </div>
    <div>
      <span>手机: <span>{{ phone }}</span></span>
    </div>
  </div>
  <button class="btn">点我</button>

</body>
<script src="./MVVM.js"></script>
<script>

  document.querySelector('.btn').addEventListener('click', () => {
    app.setValue('phone', '214122321321')
  })
  const obj = {
    username: '',
    password: '',
    phone: '',
  }

  const app = new MVVM('#app', obj)


</script>

下面是js部分

// 手写v-model
const varibleReg = /{{(.+?)}}/
// 1 先实现数据劫持
// 2 绑定input
// 3 渲染dom节点内容
class MVVM {

  constructor(el, data) {
    this.el = document.querySelector(el)
    this._data = data
    this.domPool = {}
    this.init()
  }

  setValue(key, value) {
    this.data[key] = value
  }

  bindInput(el) {
    const inputs = el.querySelectorAll('input[v-model]')
    inputs.forEach(input => {
      input.addEventListener('input', this.handleInput.bind(this, input))
    })
  }

  handleInput(input) {
    const key = input.getAttribute('v-model')
    const _value = input.value
    this.data[key] = _value
  }

  bindDom(el) {
    const childNodes = el.childNodes
    childNodes.forEach(item => {
      const _value = item?.nodeValue
      if (item?.nodeType === 3 && varibleReg.test(_value)) {
        const key = _value.match(varibleReg)[1].trim()
        this.domPool[key] = item.parentNode
        item.parentNode.innerText = this.data[key]
      }
      // 递归函数
      !!item?.childNodes.length && this.bindDom(item)
    })
  }

  initData() {
    this.data = {}
    for (const key in this._data) {
      Object.defineProperty(this.data, key, {
        get: () => this._data[key],
        set: newVal => {
          this._data[key] = newVal
          this.domPool[key].innerText = this.data[key]
        }
      })
    }
  }

  init() {
    this.initData()
    this.bindDom(this.el)
    this.bindInput(this.el)
  }

}

杨秦
9 声望0 粉丝