数据响应式

12/28/2020 Vue

目的: 是为了实现一个简易版本的 vue 使用Proxy进行数据劫持,实现了渲染数据和双向绑定的功能

<div id="app">
  <p>{{msg}}</p>
  <p>{{num}}</p>
  <input v-model="num" />
</div>
// Vue的实现过程
class Vue extends EventTarget {
  constructor(option) {
    super()
    this.option = option
    this._data = option.data
    this.el = document.querySelector(option.el)
    this.observe(this._data)
    this.compileNode(this.el)
  }

  observe(data) {
    let _self = this
    this._data = new Proxy(data, {
      set(target, prop, newValue) {
        let event = new CustomEvent(prop, {
          detail: newValue,
        })
        _self.dispatchEvent(event)
        return Reflect.set(...arguments)
      },
    })
  }

  compileNode(el) {
    let child = el.childNodes
    ;[...child].forEach((node) => {
      if (node.nodeType === 3) {
        let text = node.textContent
        let reg = /\{\{\s*([^\s\{\}]+)\s*\}\}/g
        if (reg.test(text)) {
          let $1 = RegExp.$1
          Object.keys(this._data).includes($1) &&
            (node.textContent = text.replace(reg, this._data[$1]))
          this.addEventListener($1, (e) => {
            node.textContent = text.replace(reg, e.detail)
          })
        }
      } else if (node.nodeType === 1) {
        let attr = node.attributes
        if (attr.hasOwnProperty('v-model')) {
          let key = attr['v-model'].nodeValue
          node.value = this._data[key]
          node.addEventListener('input', (e) => {
            this._data[key] = node.value
            console.log(this._data[key])
          })
        }
        this.compileNode(node)
      }
    })
  }
}

// 使用Vue
let app = new Vue({
  el: '#app',
  data: {
    msg: 'Hello',
    num: 2,
  },
})
    希望像星光一样闪烁
    文雀