这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战
这篇文章我们来讲一下refs的使用,以及我们需要注意的地方。
如何使用
ref
在之前的很多文章都提到过ref,ref 对象具有指向内部值的单个 property .value,使用如下:
const count = ref(0)
console.log(count.value) // 0
这个方法也是也把数据变成响应式的。
unref
对比ref,就是为了获取原始数据本身,这跟 val = isRef(val) ? val.value : val 的语法糖函数有关,使用如下:
const title = ref('hello world')
console.log(unref(title)) //'hello world'
如果把ref比喻穿上马甲,那么unref就是脱掉马甲,可以直接使用数据。
toRef
官方说,可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。使用如下:
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
上述示例中,当state.foo改变的时候,fooRef也随之发生变化;反之,亦然。toRef在你要将 prop 的 ref 传递给复合函数时很有用。
假定一个组件如下:
app.component('my-compoent', {
props: ['msg', 'name'],
setup(props) {
const msg = toRef(props, 'msg').value.toLocaleUpperCase()
const name = toRef(props, 'name').value.toLocaleUpperCase()
return {
msg, name
}
},
render() {
return h('h1', {}, `${this.msg},${this.name}!`)
}
})
组件使用如下:
<my-compoent msg="Hi" name="slifree"></my-compoent>
如果我们不在setup里面用toRef处理props,我们的渲染结果是:Hi,slifree!,处理后的结果是:HI,SLIFREE!。
toRefs
将响应式对象转换为普通对象,类比toRef为源响应式对象上的 某个 property新创建一个 ref,toRefs为源响应式对象上的 每一个 property 新创建一个 ref,这在我们项目中经常用到,如下所示:
setup() {
const state = reactive({
foo: 1,
bar: 2
})
return {
...toRefs(state)
}
}
用了toRefs和...后,在模板语法中就不用 state.foo 这种方式取值了,而可以直接使用foo,如下:
<h1>{{foo}} {{bar}}</h1>
isRef
检查值是否为一个 ref 对象。使用如下:
const title = ref('hello world')
console.log(isRef(title)); //true
customRef
我们可以根据自己需求创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 track 和 trigger 函数作为参数,并且应该返回一个带有 get 和 set 的对象。
假定我们自定义一个变量防抖函数如下:
function useDebouncedRef(value, delay = 2000) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
return {
text: useDebouncedRef('hello')
}
使用时如下:
<input v-model="text" />
这种我们在改变input值的时候就不用担心get的频繁出发。
shallowRef
创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的。使用如下:
const foo = shallowRef({
title:'hello'
})
foo.value={}
改变 foo 的值是可以跟踪到的,但是这个值不是响应式的,也就是说isReactive(foo.value)===false。
triggerRef
手动执行与 shallowRef 关联的任何副作用。使用如下:
watchEffect(() => {
console.log(foo.value.title)
})
triggerRef(foo)
如果foo.value在副作用(watchEffect)中进行了侦听,那么每次我们执行triggerRef函数的时候,就会触发副作用函数。
总结
-
在实际开发中
toRefs配合展开运算符...是很常用的,我们要熟练的掌握它。 -
其他的api我们要根据自己的需求去合理的使用它们。
想了解更多文章,传送门已开启:回首Vue3目录篇 !