vue响应式原理——发布订阅,数据劫持

订阅器模型

// 订阅器模型
const Dep = {
  clientList: {},
  // 订阅
  listen(key, fn) {
    (this.clientList[key] ??= []).push(fn)
  },
  // 发布
  trigger() {
    const key = Array.prototype.shift.call(arguments)
    const fns = this.clientList[key]
    if (!fns || fns.length === 0) return
    for (let i = 0, fn; fn = fns[i++];) {
      fn.apply(this, arguments)
    }
  }
}

Object.defineProperty 数据劫持

/**
* 数据劫持
* @param {object} val 传递的对象
* @param {object} val.data 被劫持的对象
* @param {string} val.tag 唯一的key
* @param {string} val.datakey 被监听对象的属性
* @param {string} val.selector 获取dom元素的选择器
*/
const dataHi = ({
  data,
  tag,
  datakey,
  selector
}) => {
  let value = ''
  const el = document.querySelector(selector)
  // 订阅
  Dep.listen(tag, (text) => {
    el.innerHTML = text
  })

  Object.defineProperty(data, datakey, {
    get() {
      console.log('取值')
      return value
    },
    set(val) {
      console.log('写值')
      value = val
      // 发布
      Dep.trigger(tag, val)
    }
  })
}

使用

  • 然后改变 data.one 的值就可以对应的改变 dom 元素
const obj = {}

dataHi({
  data: obj,
  tag: 'view-1',
  datakey: 'one',
  selector: '.box-1'
})
posted @ 2022-09-15 14:26  懒惰ing  阅读(56)  评论(0编辑  收藏  举报