customRef
custom译为自定义,创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
虽然是自定义,但是也不是完全都是自己写的,可以借助customRef。
下面通过案例演示一下customRef的使用,这个案例也是vue官网提供的防抖效果案例
自定义ref函数
ref其实也是一个函数,我们可以自己创建
这样一个最基本的自定义ref函数就完成了,接下来就可以引入customRef编写逻辑了
引入customRef
想要使用,就得引入customRef
import {customRef } from 'vue'
使用customRef
customRef其实也是一个函数,且必须要返回出来这个customRef函数
但是这么写确报错了:
这是一个底层的错误,因为少了参数,它的参数是一个函数
customRef的参数和返回值
想要解决上面的错误,需要给customRef进行传参,vue设置的customRef参数是一个函数,这个函数里面就是自定义的逻辑
但是又报错了,这次的错误是没有get,其实是因为自定义函数没有返回值,vue要求为自定义函数的返回值必须是一个对象
但是又双叒叕报错了!
我们需要写两个特殊的属性:一个是get,它是一个函数,一个是set,它的值也是一个函数!
先不说逻辑怎么样,现在至少不报错了
初始化自定义ref页面数据
get
虽然不报错了,但是没有定义的数据,这是因为因为get没有返回值
有人读取数据,get函数就会被执行
我们给get返回数据即可
页面正常了,但是修改不了h3标签的数据,这是因为set没有返回值
set
和get是相反的,有人修改数据,set函数就会被执行,它有一个参数,就是修改后的最新数据
但是这样页面h4的数据还是不会变,这时候就要用到customRef的两个参数了:track,trigger
trigger
trigger有触发器的意思,它可以通知去调用get
track
track有追踪的意思,追踪属性的改变。如果不追踪,那么就永远返回属性最新的值
track要在return之前调用
这样整个自定义的customReff的流程就写完了,数据也可以正常修改了
这时候离官方案例就差一步了,就是延迟加载值,可以使用定时器实现
自定义逻辑:延迟加载(防抖效果)
但是这样不够完美,如果输入的频率大于定时器,那么会造成页面的抖动
可以定义一个变量,每次开启定时器的时候,都把id交给这个变量,然后每次进入set的时候,就清除对应的定时器id,重新开启新的定时器
当然可以再次优化,就是把定时器的事件换成变量,由ref传参:
全部代码如下:
<template>
<input type="text" v-model="keyWord">
<h3>{{keyWord}}</h3>
</template>
<script>
import { ref,customRef } from 'vue'
export default {
name: 'App',
setup() {
// 定义一个自定义Ref函数,名称为myRef
function myRef(value,timerNum){
let timer
// 这个return返回的是自定义的ref
return customRef((track,trigger)=>{
// 这个return返回的是自定义ref里面的逻辑
return{
get(){
// 通知Vue追踪数据的变化
track()
return value
},
set(newValue){
clearTimeout(timer)
timer= setTimeout(() => {
value=newValue
// 通知vue去重新解析模板
trigger()
}, timerNum);
}
}
})
}
// let keyWord=ref('hello') // 使用vue提供的ref
let keyWord=myRef('hello',500) // 使用程序员自定义的ref
return {keyWord}
}
}
</script>
总结
- 作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
- 实现防抖效果:
<template>
<input type="text" v-model="keyword">
<h3>{{keyword}}</h3>
</template>
<script> import {ref,customRef} from 'vue'
export default {
name:'Demo',
setup(){
// let keyword = ref('hello') //使用Vue准备好的内置ref
//自定义一个myRef
function myRef(value,delay){
let timer
//通过customRef去实现自定义
return customRef((track,trigger)=>{
return{
get(){
track() //告诉Vue这个value值是需要被“追踪”的
return value
},
set(newValue){
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue
trigger() //告诉Vue去更新界面
},delay)
}
}
})
}
let keyword = myRef('hello',500) //使用程序员自定义的ref
return {
keyword
}
}
}
</script>