专栏目录请点击
代码
代码看不懂的话,可以直接结合下面的解释去看
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ref与shallowRef</title>
</head>
<body>
<h1>ref与shallowRef</h1>
<script>
// 定义拦截操作,一般我们拦截操作后进行界面的更新
const reactiveHandler = {
get(target, key) {
if (key === '_is_reactive') return true
return Reflect.get(target, key)
},
set(target, key, value) {
const result = Reflect.set(target, key, value)
console.log('数据已更新, 去更新界面')
return result
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
console.log('数据已删除, 去更新界面')
return result
}
}
// 定义reactive函数,通过递归实现全部的响应式(对于每一个对象进行代理)
function reactive(target) {
if (target && typeof target === 'object') {
if (target instanceof Array) { // 数组
target.forEach((item, index) => {
target[index] = reactive(item)
})
} else { // 对象
Object.keys(target).forEach(key => {
target[key] = reactive(target[key])
})
}
const proxy = new Proxy(target, reactiveHandler)
return proxy
}
return target
}
// shallowRef主要使用对象的getter和setter来拦截实现响应式
function shallowRef(target) {
const result = {
_value: target, // 用来保存数据的内部属性
_is_ref: true, // 用来标识是ref对象
get value() {
return this._value
},
set value(val) {
this._value = val
console.log('set value 数据已更新, 去更新界面')
}
}
return result
}
// ref 可以接收对象或者基本数据类型,如果接收的是对象,那么最终调用的是reactive,其他还是使用对象的getter和setter
function ref(target) {
if (target && typeof target === 'object') {
target = reactive(target)
}
const result = {
_value: target, // 用来保存数据的内部属性
_is_ref: true, // 用来标识是ref对象
get value() {
return this._value
},
set value(val) {
this._value = val
console.log('set value 数据已更新, 去更新界面')
}
}
return result
}
// 只处理基本类型的浅响应式,不处理对象的响应式
const shallowRef1 = shallowRef({a:1})
shallowRef1.value = {b:2} // 可以更新界面
shallowRef1.value.b = 3 // 不会更新界面
// 测试ref
// 基本类型
const ref1 = ref(0)
// 引用类型
const ref2 = ref({a:1,b:{c:2}})
ref1.value++ // 可以更新界面
ref2.value.b.c = 3 // 可以更新界面
</script>
</body>
</html>
解释
- 在实现基本数据类型的浅响应式的时候,我们并不需要
proxy
来进行处理,只需要使用对象的getter
和setter
来进行实现就可以了 - 我们在写
ref
和shallowRef
发现定义了一个_is_ref
,这个属性似乎没有用到,当然写这个属性的目的就是,下面的isRef
这个函数来进行铺垫的