# 数据响应式

目的: 是为了实现一个简易版本的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
  }
})