手写基础版Vue响应式原理

1. 定义测试对象

我们新建了一个obj对象,然后`new Observe`
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <h1>0</h1>
  <script src="./index.js"></script>
  <script>
    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    new Observe(obj)

  </script>
</body>

</html>

2. 定义Observe观察者

let count = 0
function Observe (ops) {
  // 这里的ops就是我们的obj,提取ops对象中的所有键名组成的数组
  const keys = Object.keys(ops)
  // 循环遍历这个key数组
  for (let i = 0; i < keys.length; i++) {
    // 取到每一个key
    const key = keys[i]
    // 定义响应式 ops => obj, key => 对象的键名,ops[key] => 对象的键值
    defineRective(ops, key, ops[key])
  }
}

3. 定义defineRective响应式函数

function defineRective (obj, key, value) {
  // 给传过来的值定义get/set
  Object.defineProperty(obj, key, {
    get () {
      console.log(1)
      return value
    },
    set (val) {
      console.log(2)
      value = val
    }
  })
}

4. 定义更新页面的方式(假设)

// 假设这里是更新页面的方法
function update () {
  // 获取到页面的h1元素
  const h1 = document.querySelector('h1')
  // h1.innerHtml >>> 0 是将字符串转为数字
  h1.innerHTML = `我已经更新了${++count} 次了`
}

5. 测试

现在我们可以测试一下,读取obj中的值,获取设置obj中的值,看看能不能打印
const obj = {
      a: 1,
      b: 2,
      c: 3
    }
new Observe(obj)
console.log(obj.a)
obj.a = 4
console.log(obj.a)
## 浏览器打印如下:
i am get
1
i am set
i am get
4
没问题

6. 更新视图(假设)

那么既然读取对象中的数据就要刷新页面,那么我们这里就测试一下,读取一次页面就加1,我们可以在get/set中调用这个这个函数,达到更新视图的作用
function defineRective (obj, key, value) {
  // 给传过来的值定义get/set
  Object.defineProperty(obj, key, {
    get () {
      update() // 更新页面
      console.log('i am get')
      return value
    },
    set (val) {
      update()// 更新页面
      console.log('i am set')
      value = val
    }
  })
}

7. 优化defineRective响应式函数

之前我们测试的是普通的对象,假设现在我们里面对象嵌套对象,那么我们的代码能否实现响应式呢?我们可以测试一下
 const obj2 = {
      a: {
        f: 'hello'
      },
      b: {
        g: '华哥头发呢?'
      },
      c: 3
    }

   new Observe(obj2)
   console.log(obj2.a.f)
   console.log(obj2)
// 经过打印obj2发现,只有第一层对象有get/set,所有并没有实现深度相应
// 那么我们就可以深度遍历一下,如果对象的值还是一个对象的话,我们可以递归调用Observe函数来为我们的对象添加get/set方法


// 响应式
function defineRective (obj, key, value) {
  // 如果值还是一个对象的话,递归调用一下
  if (typeof value === 'object') Observe(value)
  // 给传过来的值定义get/set
  Object.defineProperty(obj, key, {
    get () {
      update() // 更新页面
      console.log('i am get')
      return value
    },
    set (val) {
      update()// 更新页面
      console.log('i am set')
      value = val
    }
  })
}

结尾

下期我们来讲讲 用Proxy来代替Object.defineProperty的优势,敬请期待!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值