首页 > 其他分享 >手写基础版Vue响应式原理

手写基础版Vue响应式原理

时间:2023-02-01 10:04:58浏览次数:39  
标签:Vue obj log get value 响应 set key 手写


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的优势,敬请期待!!


标签:Vue,obj,log,get,value,响应,set,key,手写
From: https://blog.51cto.com/u_14389461/6030672

相关文章