Vue3响应式进阶API
我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情
shallowRef
shallow有浅层的意思,shallowRef
是一种浅层形式的ref
,浅层式的API创建的状态只在其顶层是响应式的,也就是说它只对.value
的访问是响应式的,不会对内部值进行深层递归的响应式转换。
const user = shallowRef({
name: '张三',
age: 18
})
user.value.name = '李四' // 不会触发更新
// 会触发更新
user.value = {
name: '李四',
age: 19
}
const list = shallowRef([{name: '张三'}])
const addUser = () => {
list.value.push({name: '李四'}) // 不会触发更新
// 会触发更新
list.value = [
{name: '张三'},
{name: '李四'}
]
}
shallowRef
可用于对大型数据结构的性能优化,例如一些比较大的列表数据,我们平时开发中通常都只需要更换最顶层的列表数据而不需要改变列表内部的值,这时可以使用shallowRef
,减少一些不必要的响应式消耗。
triggerRef
triggerRef
用于强制触发依赖于一个浅层ref
的副作用。
如前面的代码示例中,当我们使用shallowRef
后,向列表添加一个对象后并不会触发更新,这时就可以用triggerRef
进行手动更新。
const list = shallowRef([{name: '张三'}])
const addUser = () => {
list.value.push({name: '李四'}) // 不会触发更新
triggerRef(list) // 手动触发list更新
}
shallowReactive
shallowReactive
与shallowRef
类似,它是reactive
的浅层形式。与shallowRef
稍有不同,shallowReactive
创建的对象里只有根层级的属性是响应式的,更深层的属性会失去响应式。
const user = shallowReactive({
name: '张三',
son: {
name: '小张'
}
})
user.name = '李四' // 更改状态自身的属性会触发更新
user.son.name = '李四' // 下层嵌套对象不会触发更新
shallowReadonly
与readonly
不同,shallowReadonly
只有根层级的属性变成只读,其他深层级的属性可以被更改。
const user = shallowReadonly({
age: 28,
son: {
age: 2
}
})
// 更改状态自身的属性会失败
user.age = 30
// 可以更改下层嵌套对象
user.son.age = 3
customRef
customRef
可以创建一个自定义的ref
,你可以在内部自己控制依赖追踪和更新触发的时机。
customRef
是一个函数,接收两个函数参数:track
、trigger
,返回一个对象,该对象包含get
和set
两个方法。
<template>
<input v-model="text" />
</template>
<script setup>
import { customRef } from 'vue'
const useDebouncedRef = (value, delay = 500) => {
let timeout
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
const text = useDebouncedRef('hello')
</script>
上面代码中利用customRef
实现了一个防抖ref
,在get
方法中进行正常的触发依赖追踪并返回值,而在set
方法里做了一个防抖操作,在一段固定间隔后再进行赋值和更新。
toRaw
toRaw()
可以返回由reactive()
、shallowReactive()
、readonly()
等创建的代理对象的原始对象。
通过toRaw()
拿到的原始数据,对其进行读取或更改不会引起跟踪开销或触发更新。
const user = {
name: '张三',
age: 18
}
const state = reactive(user)
const raw = toRaw(state)
console.log(raw === user) // true
markRaw
markRaw
可将一个对象标记为不可被转为代理。
const state = markRaw({
name: '张三',
age: 18
})
const user = reactive(state)
setTimeout(() => {
user.name = '李四' // 不会触发更新
}, 3000)
转载自:https://juejin.cn/post/7140635861003010084