当前位置: 首页 > news >正文

ref 和 reactive的区别与用法

在 Vue 3 中,ref 和 reactive 都是用于创建响应式数据的 API,但它们的使用场景和特性有所不同,具体区别与用法如下:

1. 核心区别

特性refreactive
处理的数据类型主要用于基本数据类型(Number、String、Boolean 等),也可用于对象 / 数组仅用于对象或数组(不能直接处理基本类型)
响应式原理通过包装成一个带 .value 属性的对象实现响应式通过 ES6 Proxy 直接代理对象实现响应式
访问方式在脚本中需通过 .value 访问 / 修改值;模板中可直接使用直接访问 / 修改属性(无需 .value
解构特性解构后仍能保持响应式(需用 toRefs 处理)直接解构会丢失响应式

2. 用法示例

(1) ref 的用法
  • 基本类型

    javascript

    运行

    import { ref } from 'vue'const count = ref(0) // 初始值为 0(基本类型)// 脚本中访问/修改需用 .value
    console.log(count.value) // 0
    count.value++ // 修改值// 模板中直接使用(无需 .value)
    // <template>{{ count }}</template>
    
  • 对象 / 数组

    javascript

    运行

    const user = ref({ name: '张三', age: 20 })
    const list = ref([1, 2, 3])// 脚本中修改需用 .value
    user.value.name = '李四'
    list.value.push(4)
    
(2) reactive 的用法
  • 仅用于对象 / 数组

    javascript

    运行

    import { reactive } from 'vue'const user = reactive({ name: '张三', age: 20 }) // 对象
    const list = reactive([1, 2, 3]) // 数组// 直接访问/修改属性(无需 .value)
    console.log(user.name) // 张三
    user.age = 21 // 修改属性
    list.push(4) // 修改数组
    
  • 注意:如果直接给 reactive 对象重新赋值,会丢失响应式(因为 Proxy 代理的是初始对象):

    javascript

    运行

    const user = reactive({ name: '张三' })
    user = { name: '李四' } // 错误!响应式丢失
    // 正确做法:修改属性而非替换整个对象
    user.name = '李四'
    

3. 如何选择?

  • 用 ref 当

    • 数据是基本类型(如数字、字符串)。
    • 希望在模板中直接使用变量(无需解构)。
    • 需要解构数据且保持响应式(配合 toRefs)。
  • 用 reactive 当

    • 数据是对象或数组,且需要直接操作属性(无需 .value)。
    • 避免手动处理 .value 的场景(如复杂对象的嵌套属性)。

4. 进阶:ref 与 reactive 的转换

  • reactive 转 ref:直接将 reactive 对象传给 ref,会自动解包(无需 .value 访问):

    javascript

    运行

    const userReactive = reactive({ name: '张三' })
    const userRef = ref(userReactive)
    console.log(userRef.value.name) // 等价于 userReactive.name
    
  • 保持解构响应式:对 reactive 对象解构时,用 toRefs 转换为 ref 集合:

    javascript

    运行

    import { reactive, toRefs } from 'vue'const user = reactive({ name: '张三', age: 20 })
    const { name, age } = toRefs(user) // 转换为 ref 对象// 此时解构后的 name/age 仍为响应式,需用 .value 访问
    console.log(name.value) // 张三
    

总结:ref 更灵活(支持所有类型),reactive 更适合对象 / 数组的直接操作,核心区别在于是否需要 .value 和数据类型的适配。


ES6 Proxy是什么

ES6 中的 Proxy 是一种用于创建对象代理的机制,它允许你拦截并自定义对象的基本操作(如属性访问、赋值、删除、函数调用等)。简单来说,Proxy 就像一个 “中间层”,可以在目标对象的操作执行前后添加自定义逻辑,而无需修改目标对象本身。

基本语法

javascript

运行

const proxy = new Proxy(target, handler);
  • target:被代理的目标对象(可以是对象、数组、函数等)。
  • handler:一个配置对象,包含各种 “拦截器” 方法(如 getset 等),用于定义对目标对象操作的自定义行为。

常用拦截器方法

handler 对象中可以定义多种拦截器,常用的有:

  1. get(target, propKey, receiver)拦截对象属性的读取操作(如 proxy.xxx 或 proxy[xxx])。

    • target:目标对象
    • propKey:属性名
    • receiver:Proxy 实例本身(或继承 Proxy 的对象)
  2. set(target, propKey, value, receiver)拦截对象属性的赋值操作(如 proxy.xxx = value)。

    • 返回 true 表示赋值成功,false 则失败(严格模式下会报错)。
  3. has(target, propKey)拦截 in 运算符(如 xxx in proxy),返回布尔值。

  4. deleteProperty(target, propKey)拦截 delete 操作(如 delete proxy.xxx),返回布尔值表示是否删除成功。

  5. apply(target, thisArg, args)拦截函数调用(当目标对象是函数时,如 proxy(...args) 或 proxy.call(...))。

使用示例

1. 拦截属性读写(实现简单的数据验证)

javascript

运行

const user = { name: '张三', age: 20 };// 创建代理,拦截 age 的赋值操作
const userProxy = new Proxy(user, {get(target, prop) {// 读取属性时的自定义逻辑return prop in target ? target[prop] : '属性不存在';},set(target, prop, value) {// 对 age 进行赋值验证if (prop === 'age' && (typeof value !== 'number' || value < 0)) {throw new Error('年龄必须是正数');}target[prop] = value; // 合法则赋值return true;}
});console.log(userProxy.name); // 张三(触发 get)
userProxy.age = 25; // 合法赋值(触发 set)
userProxy.age = -5; // 报错:年龄必须是正数
console.log(userProxy.gender); // 属性不存在(触发 get)
2. 拦截数组操作(监控数组变化)

javascript

运行

const list = [1, 2, 3];const listProxy = new Proxy(list, {set(target, prop, value) {console.log(`数组修改:${prop} = ${value}`); // 监控修改target[prop] = value;return true;}
});listProxy.push(4); 
// 输出:
// 数组修改:3 = 4(push 会给索引 3 赋值)
// 数组修改:length = 4(push 会更新 length)

Proxy 的特点

  1. 非侵入式:无需修改目标对象,通过代理层实现逻辑,更灵活。
  2. 全面拦截:支持多种对象操作的拦截(比 ES5 的 Object.defineProperty 能拦截的操作更多,如 indelete、数组索引修改等)。
  3. 响应式基础:Vue 3 的 reactive 就是基于 Proxy 实现的 —— 通过拦截对象的 get 和 set 操作,实现数据变化时自动更新视图。

与 Object.defineProperty 的区别

  • Object.defineProperty 只能拦截特定属性的读写,而 Proxy 可以拦截对象的所有操作(包括新增属性、删除属性等)。
  • Proxy 代理的是整个对象,而 Object.defineProperty 需要逐个属性定义拦截。
  • Proxy 对数组的拦截更友好(如 pushsplice 等方法会触发拦截),而 Object.defineProperty 对数组的监控需要额外处理。

因此,Proxy 是更强大、更现代的对象拦截方案,广泛用于响应式编程、数据校验、日志监控等场景。


return prop in target ? target[prop] : '属性不存在';,prop in target是什么意思,prop是属性,target是这个对象吗

是的,你的理解是对的。

  • target 就是被 Proxy 代理的目标对象(比如示例中的 user 对象)。
  • prop 是当前要访问的属性名(比如访问 userProxy.name 时,prop 就是 'name')。

而 prop in target 是 JavaScript 的一个语法,用于判断某个属性是否存在于目标对象中,返回布尔值(true 存在,false 不存在)。

具体来说:

  • 当访问 userProxy.name 时,prop 是 'name'target 是 user 对象。因为 user 确实有 name 属性,所以 'name' in user 结果为 true,此时返回 target[prop](即 user.name 的值 '张三')。
  • 当访问 userProxy.gender 时,prop 是 'gender'target 是 user 对象。因为 user 没有 gender 属性,所以 'gender' in user 结果为 false,此时返回 '属性不存在'

简单说,prop in target 就是检查 “目标对象里有没有这个属性”,是一种常用的对象属性存在性判断方式。

http://www.dtcms.com/a/570511.html

相关文章:

  • 网站整套模板做网站哪个平台
  • asp与sql做网站莱州网站建设多少钱
  • UE C++ 代码上构建反射
  • 360建筑网官方网站网站运营编辑
  • 网站点赞怎么做邮箱域名和网站域名
  • 企业采购如何管理部门预算?
  • 三、ILA逻辑分析仪抓取及查看波形
  • asp.net网站本机访问慢网络运维需要懂什么技术
  • 网站的相关性 实用性网站建设项目登记表
  • 深圳本地做网站wordpress 文章列表只显示标题
  • notion模版 | 小胡的第二大脑[特殊字符]-任务篇
  • harmonyos的鸿蒙的跳转页面的部署
  • Godaddy优惠码网站怎么做的红豆梧州论坛
  • 商户查询缓存、商户更新缓存(opsForHash、opsForList、ObjectMapper、@Transactional、@PutMapping、RequestParam、装箱拆箱、线程池)
  • 做网站如何推销网站建设论证方案
  • 济南企业网站推广网络销售的工作内容
  • 大神自己做的下载音乐的网站域名是什么意思举个例子
  • Python中常用内置函数下【含代码理解】
  • QuickDruid
  • Java 文件上传-阿里云OSS对象存储
  • 国外 网站源码西部建设公司官网
  • 深圳做h5网站设计济南冰河世纪网站建设
  • 如何为公司做网站施工企业风险防控
  • 宁波市高等级公路建设指挥部网站wordpress建企业网站设置
  • 网站广告招商应该怎么做昆明大型网页开发企业
  • helmfile使用指南
  • 平谷做网站wordpress 百万ip
  • 网站开发兼职群网店装修网站
  • 网站开发设计资讯用php做图书管理网站
  • 博客建站系统设计网站p站