Vue 3 引入了 Composition API,为我们提供了更加灵活和强大的方式来组织组件逻辑。在本文中,我们将通过一个具体的 customRef 示例,并扩展介绍其他相关响应式 API,帮助你全面掌握 Vue 3 的响应式系统。
一、自定义响应式引用:customRef
我们先来看一个使用 customRef 实现防抖搜索的示例:
vue
复制下载
<template>
<div>
<input type="text" v-model="keyWord"/>
<h2>{{ keyWord }}</h2>
</div>
</template>
<script>
import { customRef } from 'vue';
export default {
name: 'App',
setup() {
// 自定义的防抖 ref 实现
function myRef(value, delay) {
let timer;
return customRef((track, trigger) => {
return {
get() {
console.log(`有人从myRef这个容器中读取数据了,我把${value}给他了`);
track(); // 通知Vue追踪value的变化
return value;
},
set(newValue) {
console.log(`有人把myRef这个容器中的数据改为了:${newValue}`);
clearTimeout(timer);
value = newValue;
timer = setTimeout(() => {
trigger(); // 通知Vue去重新解析模板
}, delay);
}
};
});
}
// 使用自定义ref,设置500ms防抖
let keyWord = myRef('hello', 500);
return {
keyWord
};
}
};
</script>
customRef 的核心机制:
track():在get方法中调用,用于依赖收集,告诉 Vue "这个值被读取了,需要跟踪它的变化"trigger():在set方法中调用,用于触发更新,告诉 Vue "这个值变化了,需要重新渲染"- 自定义控制:通过
customRef,我们可以完全控制何时触发更新,这在实现防抖、节流等场景中非常有用
二、其他重要的 Composition API
1. shallowReactive 与 shallowRef
shallowReactive:只处理对象最外层属性的响应式(浅响应式)shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理
使用场景:
- 当对象结构很深,但只有外层属性变化时 → 使用
shallowReactive - 当对象数据不会内部修改,而是用新对象替换时 → 使用
shallowRef
2. readonly 与 shallowReadonly
readonly:让响应式数据变为深只读shallowReadonly:让响应式数据变为浅只读
应用场景:接收来自外部的数据,确保不会被意外修改。
3. toRaw 与 markRaw
-
toRaw:将reactive创建的响应式对象转为普通对象- 对普通对象的操作不会触发页面更新
-
markRaw:标记对象,使其永远不会成为响应式对象- 适用于第三方类库、大数据列表等场景,提高性能
4. provide 和 inject
实现祖孙组件通信的利器:
javascript
复制下载
// 父组件
setup() {
provide('userInfo', { name: '张三', age: 25 });
}
// 子组件
setup() {
const userInfo = inject('userInfo');
return { userInfo };
}
5. 响应式数据判断工具
isRef:检查是否为 ref 对象isReactive:检查是否为 reactive 创建的响应式代理isReadonly:检查是否为 readonly 创建的只读代理isProxy:检查是否为 reactive 或 readonly 创建的代理
三、Composition API 的优势
- 更好的代码组织:将相关功能逻辑组织在一起,提高代码可读性和可维护性
- 逻辑复用:可以轻松提取和复用响应式逻辑
- TypeScript 支持:提供更好的类型推断
- 灵活性:可以根据功能而非选项(data、methods等)来组织代码
四、实战建议
- 性能优化:对于大型对象或列表,合理使用
shallowReactive和shallowRef - 数据保护:使用
readonly保护不应被修改的数据 - 防抖节流:利用
customRef优雅地实现输入防抖等效果 - 组件通信:对于深层嵌套组件,使用
provide/inject替代多层 props 传递