美文网首页
vue响应式原理

vue响应式原理

作者: hello_world_bye | 来源:发表于2019-02-24 15:19 被阅读0次

    参考: vue2.0源码分析之理解响应式架构
    ](https://segmentfault.com/a/1190000007334535)

    // 参考:https://segmentfault.com/a/1190000007334535
    
    function VNode(tag, data, children, text) {
      return {
        tag: tag,
        data: data,
        children: children,
        text: text
      }
    }
    
    class Vue {
      constructor(options) {
        this.$options = options
        this._data = options.data
        Object.keys(options.data).forEach(key => this._proxy(key))
        observer(options.data)
        // 调用watch方法时会执行render方法,该方法中会触发date[key]的get方法
        const vdom = watch(this, this._render.bind(this), this._update.bind(this))
      }
      _proxy(key) {
        const self = this
        Object.defineProperty(self, key, {
          configurable: true,
          enumerable: true,
          get: function proxyGetter () {
            return self._data[key]
          },
          set: function proxySetter (val) {
            _data[key] = val 
          }
        })
      }
      _update() {
        console.log("我需要更新");
        const vdom = this._render.call(this)
      }
      _render() {
        return this.$options.render.call(this)
      }
      __h__(tag, attr, children) {
        return VNode(tag, attr, children.map((child)=>{
          if(typeof child === 'string'){
            return VNode(undefined, undefined, undefined, child)
          }else{
            return child
          }
        }))
      }
      __toString__(val) {
        return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);
      }
    }
    
    function observer(value, cb){
      Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))
    }
    
    function defineReactive(obj, key, val, cb) {
      const dep = new Dep()
      Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: ()=>{
          if(Dep.target){
            console.log('现在的值:', val)
            dep.add(Dep.target)
          }
          return val
        },
        set: newVal => {
          if(newVal === val)
            return
          val = newVal
          dep.notify()
        }
      })
    }
    function watch(vm, exp, cb){
      Dep.target = cb // Dep相当于是一个全局变量
      let vdom = exp()
      Dep.target = null //清空Dep,区别是普通的 get还是查找依赖时的 get
      return vdom
    }
    
    class Dep {
      constructor() {
        this.subs = []
      }
      add(cb) {
        this.subs.push(cb)
      }
      notify() {
        this.subs.forEach((cb) => cb())
      }
    }
    Dep.target = null
    // --------------------
    var demo = new Vue({
      el: '#demo',
      data: {
        text: "before",
      },
      render(){
        return this.__h__('div', {}, [
          this.__h__('span', {}, [this.__toString__(this.text)])
        ])
      }
    })
     setTimeout(function(){
       demo.text = "after"
     }, 3000)
    console.log('Dep.target', Dep.target)
    console.log('demo.text', demo.text)
    

    相关文章

      网友评论

          本文标题:vue响应式原理

          本文链接:https://www.haomeiwen.com/subject/ligjyqtx.html