美文网首页
vue响应式简易版

vue响应式简易版

作者: videring | 来源:发表于2019-10-11 16:42 被阅读0次

    参考:
    1
    2

    深入响应式原理
    • 完整源码:
    class Observer {
      constructor(obj) {
        this.walk(obj)
      }
      walk(obj) {
        Object.keys(obj).forEach(prop => {
          this[prop] = obj[prop]
          this.proxyData(obj, prop)
          this.defineReactive(this, prop, obj[prop])      
        })
      }
      proxyData(obj, prop) {
        let _this = this
        Object.defineProperty(obj, prop, {
          get() {
            let tmp = _this[prop]
            return tmp
          },
          set(newVal) {
            _this[prop] = newVal
          }
        })
      }
      defineReactive(obj, prop, val) {
          let dep = new Dep()
          Object.defineProperty(obj, prop, {
            get() {
              console.log(`${prop} - 被读取!`)
              dep.getDeps()  // 依赖收集
              return val
            },
            set(newVal) {
              if (newVal == val) return
              val = newVal
              console.log(`${prop} - 被修改!`)
              dep.notify()  // 运行所有callback       
            }
          })
      }
    }
    
    class Watcher {
      constructor(obj, prop, computed, callback) {
        this.getVal(obj, prop, computed, callback)
      }
    
      getVal(obj, prop, computed, callback) {
        Object.defineProperty(obj, prop, {
          get() {
            Dep.target = callback
            console.log(`computed属性 - ${prop}被读取!`)
            return computed()
          },
          set() {
            console.error('计算属性不可被修改!')
          }
        })
      }
    }
    
    class Dep {
      constructor() {
        this.deps = []
      }
      getDeps() {
        if (!Dep.target || this.deps.includes(Dep.target)) return
        console.log('依赖添加', Dep.target)
        this.deps.push(Dep.target)
      }
      notify() {
        this.deps.forEach(dep => {
          dep()
        })
      }
    }
    
    let man = {
      height: 180,
      weight: 70,
      wealth: 100000000
    }
    
    new Observer(man)
    
    new Watcher(man, 'strength', () => {
      let {height, weight} = man
      if (height > 160 && weight > 70) return 'strong'
      return 'weak'
    }, () => {
      console.log(`i am so`)
    })
    new Watcher(man, 'isGreat', () => {
      let {height, weight, wealth} = man
      if (height > 180 && weight > 70 && wealth > 100000) return 'Great!'
      return 'not good enough ...'
    }, () => {
      console.log(`they say i am ${man.isGreat}`)
    })
    console.log(man.strength) // 触发watcher getter
    console.log(man.isGreat) // 触发watcher getter
    

    相关文章

      网友评论

          本文标题:vue响应式简易版

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