Skip to content

Instantly share code, notes, and snippets.

@njleonzhang
Last active November 2, 2016 09:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save njleonzhang/0b6a0bfe00b069e9a7a3300051bfdeb9 to your computer and use it in GitHub Desktop.
Save njleonzhang/0b6a0bfe00b069e9a7a3300051bfdeb9 to your computer and use it in GitHub Desktop.
Vue 2.0 reactive principle
class Vue {
  constructor(options) {
    this.$options = options
    this._data = options.data
    // proxy所有的data属性
    Object.keys(options.data).forEach(key => this._proxy(key))
    // 递归的为数据定义get和set
    observer(options.data)
    // 通过调用render进行依赖收集,从而将_render方到相关data属性的watcher队列中 (1)
    const vdom = watch(this, this._render.bind(this), this._update.bind(this))  
    console.log(vdom)
  }
  
  ......
}


function watch(vm, exp, cb) {
  Dep.target = cb // (2) _update赋给Dep.target,render函数相关的属性的get方法里会将_update放到其观察者列表里
  return exp()    // (3) 执行_render,一方面返回虚拟DOM。另一方面,会导致render函数里的vue.$data的属性被访问,从而触发get方法
}

_update() {
  console.log("我需要更新");
  const vdom = this._render.call(this)
  console.log(vdom);
}

_render() {
  return this.$options.render.call(this)      // render里会访问一些变量,触发这些变量的get,返回的是虚拟dom
}

function defineReactive(obj, key, val, cb) {
    const dep = new Dep()
    Object.defineProperty(obj, key, {
      enumerable: true,
      configurable: true,
      get: ()=> {
        if(Dep.target){       
          dep.add(Dep.target) // 被访问的变量的get被触发,则render方法会被加入该变量的watch队列。强无敌!!!!
        }
        return val
      },
      set: newVal => {
        if(newVal === val)
          return
        val = newVal
        dep.notify()
      }
    })
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment