Object.defineProperty模拟Vue中的响应式数据

通过Object.defineProperty模拟实现Vue中,数据变化,视图跟着变化的效果。

html代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      font-size: 20px;
    }

    .box {
      box-sizing: border-box;
      width: 300px;
      border: 2px solid #aaa;
      padding: 10px;
      margin: 0 auto;
    }

    .box div {
      padding: 10px 0;
    }
  </style>
</head>
<body>
  <div class="box">

    <div class="name-line">
      姓名:<span></span>
    </div>

    <div class="age-line">
      年龄:<span></span>
    </div>

    <div class="bankMoney-line">
      银行中的钱:<span></span>
    </div>

    <div class="wechatMoney-line">
      微信中的钱:<span></span>
    </div>

    <div class="totalMoney-line">
      总的钱:<span></span>
    </div>
  </div>

  <script src="./index.js"></script>
</body>
</html>

js代码:

const user = {
  name: '张三',
  age: 18,
  bankMoney: 2000,
  wechatMoney: 200
}

for (let key in user) {
  // 内部的临时变量
  let interVal = user[key]

  // 函数数组,保存着读取了当前属性的函数
  const funcs = []

  Object.defineProperty(user, key, {
    get: () => {
      // 将读取了当前属性的函数存入数组中
      if (!funcs.includes(window.__func) && window.__func) {
        funcs.push(window.__func)
      }

      return interVal
    },
    set: (val) => {
      interVal = val

      // 重新执行与当前属性相关的函数
      for (let i = 0; i < funcs.length; i++) {
        funcs[i]()
      }
    }
  })
}

function renderName () {
  document.querySelector('.name-line span').textContent = user.name
}

function renderAge () {
  document.querySelector('.age-line span').textContent = user.age
}

function renderBankMoney () {
  document.querySelector('.bankMoney-line span').textContent = user.bankMoney
}

function renderWechatMoney () {
  document.querySelector('.wechatMoney-line span').textContent = user.wechatMoney
}

function renderTotalMoney () {
  document.querySelector('.totalMoney-line span').textContent = user.bankMoney + user.wechatMoney
}

function execFunc (fn) {
  window.__func = fn
  fn()
  window.__func = null
}

execFunc(renderName)
execFunc(renderAge)
execFunc(renderBankMoney)
execFunc(renderWechatMoney)
execFunc(renderTotalMoney)

数据不做修改:

在这里插入图片描述

当数据修改后,视图自动更新:

// 随意改变数据,能够让视图变化
user.age = 22
user.bankMoney = 3000
user.wechatMoney = 100

在这里插入图片描述

原理简要说明:

利用Object.defineProperty()对user对象中的每个属性进行属性描述符的重写,当运行了需要调用该属性的函数时,将函数存入数组。之后,将数据修改时,重新执行一遍数组中的所有函数,因此,视图中的数据得以更新。

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值