回首Vue3之API篇(九)

336 阅读3分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

这篇文章我们来讲一下refs的使用,以及我们需要注意的地方。

如何使用

ref

在之前的很多文章都提到过refref 对象具有指向内部值的单个 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新创建一个 reftoRefs为源响应式对象上的 每一个 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函数的时候,就会触发副作用函数。

总结

  1. 在实际开发中toRefs配合展开运算符...是很常用的,我们要熟练的掌握它。

  2. 其他的api我们要根据自己的需求去合理的使用它们。

想了解更多文章,传送门已开启:回首Vue3目录篇