Vue3中常用的API-利用customRef实现延迟加载(防抖效果)

1,531 阅读3分钟

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>