<button @click="changeMsg">change</button>
<div>{{ message }}</div>
//接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。
const message = ref('hello world')
const mum = 1
const changeMsg = () => {
message.value = 'change msg'
console.log(message.value); // change msg
}
//isRef 判断是不是一个ref对象
console.log(isRef(message)); // true
console.log(isRef(mum)); // false
shallowRef
//创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的
//修改其属性是非响应式的这样是不会改变的
<template>
{{sum}} 和 {{sums.name}} 和 {{sums.age}}
<button @click="changeSum">sum加一</button>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改person对象</button>
</template>
<script setup>
import { ref, isRef,shallowRef,customRef , reactive, shallowReactive,readonly } from 'vue'
const sum = shallowRef(0)
const sums = shallowRef({
name:'张三',
age:20
})
const changeSum = () => {
sum.value++
console.log(sum.value); // 1
}
const changeName = () => {
sums.value.name = '李四'
console.log(sums.value.name); // 李四 视图不会改变
}
const changeAge = () => {
sums.value.age = 30
console.log(sums.value.age); // 30 视图不会改变
}
const changePerson = () => {
sums.value = {name:'Tom',age:56} //都会改变
}
//如果先调用changeName 后再调用changeSum 这样名字视图也会改变,调用changePerson 同理
</script>
customRef() 是 Vue 3 中新增的 API,用于创建自定义 ref,并对其依赖项跟踪和更新触发进行显式控制。
用途
实现防抖/节流:通过控制依赖项收集和更新触发时机,可以实现防抖/节流功能。
自定义计算属性:可以根据特定逻辑计算值,并控制何时更新视图。
优化性能:可以避免不必要的更新,提升性能。
工作原理
customRef() 接收一个工厂函数作为参数,该函数接收 track 和 trigger 两个函数作为参数,并返回一个带有 get 和 set 方法的对象。
track:用于收集依赖项。在 get 方法中调用,收集该 ref 所依赖的响应式数据。
trigger:用于触发更新。在 set 方法中调用,通知依赖项更新视图。
实现一个防抖的 ref
<template>
<input type="text" v-model="name" placeholder="请输入内容" />
<template>
<script setup>
import { ref, isRef,shallowRef,customRef , reactive, shallowReactive,readonly } from 'vue'
const name = customRef((track, trigger) => {
let timer
let text
return {
get() {
track()
return text;
},
set(newValue) {
timer && clearInterval(timer)
timer = setInterval(() => {
console.log('触发了set' ,newValue);
text = newValue
trigger()
clearInterval(timer)
}, 1000)
}
}
})
</script>