Vue3.0 —— 常用的 Compoition API 之 reactive 函数 以及 响应式原理 Proxy/Reflect
1. reactive 函数
- 作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用 ref 函数)
- 语法: const 代理对象 = reactive(源对象)接收一个对象(或数组),返回一个代理对象(proxy对象)
- reactive 定义的响应式数据是 "深层次的"
- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作
<template>
<h1>基本信息</h1>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h2>工作类型:{{person.job.type}}</h2>
<h2>薪水:{{person.job.salary}}</h2>
<h2>测试的数据c:{{person.job.a.b.c}}</h2>
<h2>爱好:{{person.hobby}}</h2>
<button @click="changeInfo">改变信息</button>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
// 简单测试 setup,暂时不做响应式
setup() {
// 数据
let person = reactive({
name: '张三',
age: 18,
job: {
type: '攻城狮',
salary: '30k',
a: {
b: {
c: 666
}
}
},
hobby: ["抽烟", "喝酒", "烫头"]
})
// 方法
function changeInfo() {
person.name = '李四'
person.age = 88
// console.log(job)
person.job.type = '鼓励师'
person.job.salary = '50k'
person.job.a.b.c = 999
person.hobby[0] = "学习"
}
// 返回一个对象(常用)
return {
person,
changeInfo,
}
}
}
</script>
2. Vue 3.0 中的响应式原理
vue 2.x 的响应式
- 实现原理:
- 对象类型:通过 Object.defineProperty() 对属性的 读取 / 修改 进行拦截 (数据劫持)。
- 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
Object.defineProperty(data, 'count', {
get() {},
set() {},
});
- 存在问题:
- 新增属性/删除属性,界面不会更新。
- 直接通过下标改变数组,界面不会自动更新。
vue 3.0 的响应式
- 实现原理:
- 通过 Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写 / 属性的添加 / 属性的删除等。
- 通过 Reflect (反射):对被代理对象的属性进行操作。
- MDN 文档中描述的 Proxy 与 Reflect:
- Proxy:https://developer.mozila.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- Reflect:https://developer.mozila.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
const p = new Proxy(person, {
// 拦截读取属性值
get(target, prop) {
return Reflect.get(target, prop);
},
// 拦截设置属性值或添加新属性
set(target, prop, value) {
Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty(target, prop) {
return Reflect.delete(target, prop);
}
})
proxy.name = 'tom'
<script>
const person = {
name: '张三',
age: 18
};
// 模拟 vue2 的响应式
//#region
// let p = {}
// Object.defineProperty(p, 'name', {
// configurable: true,
// get() {
// console.log(`有人读取person的name属性`)
// return person.name
// },
// set(value) {
// console.log(`有人修改person的name属性`,value)
// person.name = value
// }
// });
// Object.defineProperty(p, 'age', {
// configurable: true,
// get() {
// console.log(`有人读取person的age属性`)
// return person.age
// },
// set(value) {
// console.log(`有人修改person的age属性`,value)
// person.age = value
// }
// });
//#endregion</script>
- reactive 对比 ref
- 从定义数据角度对比:
- ref 用来定义:基本类型数据
- reactive 用来定义:对象或数组类型数据
- 备注:ref 也可以用来定义 对象或数组类型数据,它内部会自动通过 reactive 转为 代理对象
- 从原理角度对比:
- ref 通过 Object.defineProperty() 的 get 与 set 来实现响应式(数据劫持)
- reactive 通过使用 Proxy 来实现响应式(数据劫持),并通过 Reflect 操作 源对象 内部的数据
- 从使用角度对比:
- ref 定义的数据:操作数据需要 .value,读取数据时模板中直接读取不需要 .value
- reactive 定义的数据:操作数据与读取数据:均不需要 .value
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码