Skip to content

shallowRef, shallowReactive

  • 不需要递归地处理对象的每一层时(例如约定传入的数据是一个层级很深的对象,且不需要修改其深层属性),shallowRef 就非常有用。它可以帮助你优化性能 只处理第一层的响应式数据,只有顶层数据是响应式的
ts
let person = shallowRef({
		name:'张三',
		age:18
	})
//这里的第一层数据是person.value
person.value = {name:'1',age:15}//可以修改
person.value.name = '2'//不可修改

readonly

  • 将响应式数据转换为只读状态,从而确保数据不会被意外修改,此时 Vue 调试工具中也无法修改这些值;
  • 单向关联的(深只读副本),即 let x = readOnly(Object:sum) 时,传入常引用的 x 是只读的,但是仍然可以通过直接修改 sum 的方式更改其属性;
  • 当拿到一个公共的响应式对象,可以用 readOnly 进行只读访问,避免原对象属性的意外更改。
  • 保护全局状态或配置不可修改

shallowReadOnly

  • 只有第一层数据是只读,深层数据可以被修改

toRaw

  • 提取一个响应式对象的原始对象,如果从这个 toRaw 对象处理数据的话,原始对象的数据也会被修改
  • 需要临时修改一个对象的数据且不触发视图更新
  • 将数据传递给后端

markRaw

  • 标记一个对象,使其永远不会成为响应式对象

customRef

首先定义一个双向绑定数据的两种状态:

  • 读取 get:插值语法等
  • 修改 setinput 引起的数据变化等

返回一个带有 getset 方法的对象,一般来说,track() 应该在 get() 方法中调用,而 trigger() 应该在 set() 中调用。 在读取响应式数据的时候调用 get,此时要用 track 确保 vue 正确收集到依赖,当该属性的值发生变化的时候,通过调用 trigger 函数通知所有依赖于该属性的副作用全部重新执行,保证数据正确。

[!NOTE|aside-r] 副作用 副作用是指在组件的生命周期中发生的除了更改数据状态以外的其他操作或函数调用。这些操作通常包括对元素的操作、发送网络请求、订阅/取消订阅事件等。它们可能会对组件的外部产生影响,如修改全局变量、操作 DOM、打印日志等。


html
<template>
    <div>msg {{ msg }}</div>
    <input v-model='msg' />
</template>

<script setup lang='ts' name='test'>
import { ref, reactive, toRaw, customRef} from 'vue'
import useTimeout from './useTimeout';

let {msg} = useTimeout('hello',2000)

</script>
<style scoped>

</style>
ts
//hook
import { customRef } from "vue"

export default function useTimeout(initValue: string, delay: number) {
    let timer: number//存储的是定时器的id,所以是number类型

    let msg = customRef((track, trigger) => {
        return {
            get() {
                track()
                return initValue
            },
            set(newValue) {
                clearTimeout(timer)
                timer = setTimeout(() => {
                    initValue = newValue
                    trigger()
                }, delay);
                //取消定时器后重新设置定时器
            }
        }
    })
    return {msg}
}