vue响应式简单实现

x33g5p2x  于2022-03-05 转载在 Vue.js  
字(2.8k)|赞(0)|评价(0)|浏览(576)

一、写在前面
关于MVVM开发模式,不得不说其响应式原理。响应式是MVVM架构和MVP之间最为显著的区别。在以前使用MVP架构进行前端开发时,其中间层p需要处理的逻辑特别多,导致比较臃肿。随着MVVM架构的出现,大大减少了中间层处理的业务逻辑。原因是其响应式原理,视图可以触发其中的某一个指令来改变数据,当数据改变时,视图也会随之刷新。下面我们将简单实现一个响应式。
二、vue2和vue3的响应式的区别
vue2中我们对响应式数据进行监听时,使用的是Object.defineProperty方法来实现的,在vue3中使用的是Proxy来实现响应式的。vue3相比于vue2来说可以监听更多类型的数据改变。
三、vue2的响应式实现

let activeFns = null

function reactive(obj) {
  Object.keys(obj).forEach(key => {
    let value = obj[key]
    Object.defineProperty(obj, key, {
      get() {
        let depend = getDepend(obj, key)
        depend.depend()
        return value
      },
      set(newValue) {
        let depend = getDepend(obj,key)
        value = newValue
        depend.notify()
      }
    })
  })
  return obj
}

class Depend {
  constructor() {
    this.deps = new Set()
  }
  depend() {
    if(activeFns) {
      this.deps.add(activeFns)
    }
  }
  notify() {
    this.deps.forEach(fn => fn())
  }
}

let wmap = new WeakMap()
function getDepend(target, key) {
  let targetMap = wmap.get(target) 
  if(!targetMap) {
    targetMap = new Map()
    wmap.set(target, targetMap)
  }
  let depend = targetMap.get(key)
  if(!depend) {
    depend = new Depend()
    targetMap.set(key, depend)
  }
  return depend
}

function watchFn(fn) {
  activeFns = fn
  fn()
  activeFns = null
}

let info = reactive({
  name: "dmc",
  age: 20
})

watchFn(function() {
  console.log("------------" + info.name  + "++++++++++++++++")
})
watchFn(function() {
  console.log("------------" + info.age  + "++++++++++++++++")
})
watchFn(function() {
  console.log("------------" + info.name  + "---------------")
})

info.name = "dl"

//打印结果
/*
------------dmc++++++++++++++++
------------20++++++++++++++++
------------dmc---------------
------------dl++++++++++++++++
------------dl---------------
*/

四、vue3的响应式实现

let activeFn = null
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      let depend = getDepend(target, key)
      depend.depend()
      return Reflect.get(target, key, receiver)
    },
    set(target, key, newValue, receiver) {
      let depend = getDepend(target, key)
      Reflect.set(target, key, newValue, receiver)
      depend.notify()
    }
  })
}

let wmap = new WeakMap()
function getDepend(target, key) {
  let targetMap = wmap.get(target)
  if(!targetMap) {
    targetMap = new Map()
    wmap.set(target, targetMap)
  }
  let depend = targetMap.get(key)
  if(!depend) {
    depend = new Depend()
    targetMap.set(key, depend)
  }
  return depend
}

class Depend {
  constructor() {
    this.deps = new Set()
  }
  depend() {
    if(activeFn) {
      this.deps.add(activeFn)
    }
  }
  notify() {
    this.deps.forEach(fn => fn())
  }
}

function watchFn(fn) {
  activeFn = fn
  fn()
  activeFn = null
}

let info = reactive({
  name: "dmc",
  age: 20
})

watchFn(function() {
  console.log("--------" + info.name + "++++++++")
})

watchFn(function() {
  console.log("********" + info.name + "0000000000")
})

watchFn(function() {
  console.log("********" + info.age + "0000000000")
})
console.log("??????????????????????????????")
info.name = "sscls"

/*
--------dmc++++++++
********dmc0000000000
********200000000000
??????????????????????????????
--------sscls++++++++
********sscls0000000000
*/

相关文章