Vue3中ref和reactive的对比

ops/2024/10/21 17:50:57/

1. ref

定义

  • 用途: 用于创建基本数据类型或单一值的响应式引用。
  • 语法: const myRef = ref(initialValue);

特性

  • 返回一个包含 .value 属性的 Proxy 对象。
  • 适用于基本数据类型(如数字、字符串、布尔值等)和单一值。
import { ref } from 'vue';const count = ref(0); // 创建一个响应式引用// 访问和修改
console.log(count.value); // 0
count.value++; // 修改值
console.log(count.value); // 1

原理

  • 代理: ref 创建的 Proxy 对象拦截对 .value 属性的访问和修改,从而实现响应式。
  • 依赖追踪: 当访问 .value 时,Vue 会记录该值的依赖,以便在值变化时通知相关组件更新。

ref通过一个RefImpl实例持有原始数据,进而使用.value属性访问和更新。而对于一个实例而言,其属性值是可以修改的。因此可以通过.value的方式为ref重新分配数据,无需担心RefImpl实例被改变进而破坏响应式:

import { ref } from 'vue';const myRef = ref({ count: 0 }); // 创建一个 ref 包含一个对象// 访问初始值
console.log(myRef.value.count); // 输出: 0// 修改原始数据的属性
myRef.value.count++; // 递增 count
console.log(myRef.value.count); // 输出: 1// 重新分配新的对象
myRef.value = { count: 10 }; // 重新分配新对象
console.log(myRef.value.count); // 输出: 10// 确保响应式仍然有效
myRef.value.count += 5; // 更新新对象的属性
console.log(myRef.value.count); // 输出: 15

RefImpl实例一直不变,只是改变其值 

2. reactive

定义

  • 用途: 用于创建对象或数组的响应式状态。
  • 语法: const myReactive = reactive(initialObject);

特性

  • 返回一个 Proxy 对象,监控整个对象的属性。
  • 适用于复杂数据结构(如对象、数组等)。
import { reactive } from 'vue';const state = reactive({ count: 0 }); // 创建一个响应式对象// 访问和修改
console.log(state.count); // 0
state.count++; // 修改值
console.log(state.count); // 1

原理

  • 代理: reactive 创建的 Proxy 对象监控对象的所有属性访问和修改。
  • 深度响应式: 可以监控嵌套对象和数组的变化,确保所有层级的属性都是响应式的。
  • 依赖追踪: 访问对象的属性时,Vue 会记录这些访问,以便在属性变化时更新相关的组件或计算属性。

reactive返回的是原始对象的代理,因此不能对其重新分配对象,只能通过属性访问修改属性值,否则会破坏掉响应式:

import { reactive, effect } from 'vue';// 创建一个响应式对象
let objectReactive = reactive({ count: 0 });// 创建副作用函数,监听数据变化
effect(() => {console.log(`数据变化了:${objectReactive.count}`);
});// 正常修改值
objectReactive.count = 1; // 输出: 数据变化了:1
objectReactive.count = 2; // 输出: 数据变化了:2// 重新分配整个对象(会导致响应式失效)
objectReactive = reactive({ count: 3 }); // 新的对象被创建,但原来的代理失效
objectReactive.count = 4; // 这不会触发 effect// 输出结束信息
console.log("结束了");
// 输出如下:
// 数据变化了:0
// 数据变化了:1
// 数据变化了:2
// 结束了

总结对比:

watch监听:

在 Vue 3 中,watch 可以直接监听自身组件中的 ref 对象,而不需要使用 getter 函数的原因是因为 ref 本身是响应式的,Vue 会自动处理对 ref 的变化监听。

1. ref 的工作原理:

  • Proxy 对象: 当您使用 ref 创建一个响应式引用时,Vue 返回的是一个 Proxy 对象。这个对象具有 .value 属性,用于存储实际的响应式值。

    const count = ref(0); // count 是一个包含 .value 的 Proxy 对象
    

2. 直接监听 ref:

  • 直接监听: 在自己的组件中,您可以直接使用 watch(refCount, callback) 来监听 refCount 的变化,因为 Vue 知道 refCount 是一个响应式对象。

    import { ref, watch } from 'vue';const refCount = ref(0);watch(refCount, () => {console.log(`refCount 数据变化了`);
    });// 修改 refCount 的值
    refCount.value++; // 这将触发 watch 的回调
    

3. 为什么可以直接监听:

  • 自动处理: Vue 的响应式系统会自动处理对 ref 的访问和修改,因此您不需要额外使用 getter 函数。watch(refCount, ...) 会在内部处理这个 ref 的代理,并在其值变化时触发回调。

  • 依赖收集: 由于您直接传递的是 ref 对象,Vue 会在执行 watch 时自动收集对这个 ref 的依赖。

4. 与 Props 的区别(父传子传递ref对象):

  • Props 解包: 当您从父组件传递一个 ref 作为 prop 到子组件时,Vue 会解包这个 ref 的值,使得子组件接收到的是原始值(例如,数字)。此时,需要使用 getter 来监听,因为 props 是只读的。

    watch(() => props.aa, (newValue, oldValue) => {console.log(`AA changed from: ${oldValue} to: ${newValue}`);
    });
    

总结

  • 直接监听 ref: 在组件内部,您可以直接监听 ref 对象,因为 Vue 的响应式系统会自动处理对这个对象的代理。
  • Props 处理: 对于从父组件传递的 ref,由于它会被解包成原始值,您需要使用 getter 函数来确保正确监听变化。

http://www.ppmy.cn/ops/127332.html

相关文章

Python-函数self详解

在Python中,self 是一个特殊的关键字,主要用于类(class)的定义中,表示类的实例(instance)本身。以下是对 self 的详细解释: 类和实例的概念: 类(Class&#…

进一步开发在线课程管理系统的功能,包括学生查看课程、提交作业、查看成绩等。

1. 学生查看课程功能 学生需要一个页面来查看他们已经注册的课程列表。我们可以在数据库中创建一个关联表 enrollments,用于记录学生注册的课程。 a. 修改数据库设计 新增一张 enrollments 表,来存储学生注册的课程信息: CREATE TABLE en…

群晖使用Docker搭建NASTool自动化观影工具并实现在线远程管理

文章目录 前言1. 本地搭建Nastool2. nastool基础设置3. 群晖NAS安装内网穿透工具4. 配置公网地址5. 配置固定公网地址 前言 本文主要分享一下如何在群晖NAS中本地部署Nastool,并结合cpolar内网穿透工具,轻松实现公网环境远程管理与访问本地NAS中储存的影…

基于SpringBoot+Vue+uniapp微信小程序的澡堂预订的微信小程序的详细设计和实现

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

ESP32-C3实现非易失变量(Arduino IDE )

1效果 网页输入数据&#xff0c;串口打印数据。掉电后数据还在 2源码 #include <WiFi.h> // 包含WiFi库&#xff0c;用于处理WiFi连接 #include <WebServer.h> // 包含WebServer库&#xff0c;用于创建Web服务器 #include <Preferences.h> // 包含Prefere…

Django发送短信

settings.py中设置 ##################################容联云短信平台账号信息############################## #容联云查看信息 RONGLIAN_ACC_ID ...... RONGLIAN_ACC_TOKEN ...... RONGLIAN_APP_ID ...... ############################################################…

基于springboot的网上服装商城推荐系统的设计与实现

基于springboot的网上服装商城推荐系统的设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xf…

[含文档+PPT+源码等]精品基于asp.net实现的超市管理系统

基于ASP.NET实现的超市管理系统背景主要源于现代超市管理的需求以及ASP.NET技术的广泛应用。以下是对该背景的具体阐述&#xff1a; 一、现代超市管理的需求 超市规模扩大&#xff1a; 随着经济的发展和人们生活水平的提高&#xff0c;超市规模不断扩大&#xff0c;商品种类和…