vue3中ref及reactive的说明

目录

1.响应式说明

2.vue3的ref及reactive的使用

3.reactive响应式失效问题

4.总结


1.响应式说明

vue的响应式是vue框架中的核心概念之一,它是指当数据发生变化时,vue能够自动更新视图。vue2的响应式是基于Object.defineProperty进行实现的。

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

vue3的响应式是通过ref及reactive来声明响应式状态。

当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。这是通过一个基于依赖追踪的响应式系统实现的。当一个组件首次渲染时,Vue 会追踪在渲染过程中使用的每一个 ref。然后,当一个 ref 被修改时,它会触发追踪它的组件的一次重新渲染。

在标准的 JavaScript 中,检测普通变量的访问或修改是行不通的。然而,我们可以通过 getter 和 setter 方法来拦截对象属性的 get 和 set 操作。

.value 属性给予了 Vue 一个机会来检测 ref 何时被访问或修改。在其内部,Vue 在它的 getter 中执行追踪,在它的 setter 中执行触发。

另一个 ref 的好处是,与普通变量不同,你可以将 ref 传递给函数,同时保留对最新值和响应式连接的访问。当将复杂的逻辑重构为可重用的代码时,这将非常有用。

当你修改了响应式状态时,DOM 会被自动更新。但是需要注意的是,DOM 更新不是同步的。Vue 会在“next tick”更新周期中缓冲所有状态的修改,以确保不管你进行了多少次状态修改,每个组件都只会被更新一次。

reactive() 将使对象本身具有响应性,响应式对象是 JavaScript 代理,其行为就和普通对象一样。不同的是,Vue 能够拦截对响应式对象所有属性的访问和修改,以便进行依赖追踪和触发更新。值得注意的是,reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的。只有代理对象是响应式的,更改原始对象不会触发更新。

2.vue3的ref及reactive的使用

①示例

<template><div id="count1">count值: {{ count }}</div><div><div>姓名:{{ student.name }}</div><div id="stu1">点赞数:{{ student.num }}</div></div><div><button @click="btnClick()">按钮</button></div>
</template>
<script setup>
// import {ref, reactive} from 'vue';
const ref = (target) => {let _value = target;return{get value() {return _value;},set value(newValue){_value = newValue;document.getElementById('count1').innerHTML = `count值: ${newValue}`;}}
}
const reactive = (target)=>{
return new Proxy(target,{get:(obj,key) =>{return obj[key];},set:(obj,key,newValue) =>{obj[key] = newValue;document.getElementById('stu1').innerHTML = `点赞数:${newValue}`;return true;}
})
}
const count = ref(0);
const student = reactive({name: '小李',num: 0
})const btnClick = () => {count.value++;student.num++;
}
</script>

②说明

上面是一个简单的模拟ref及reactive的实现的示例。

ref说明:

ref可以声明任何类型的变量,包含基本类型及复杂类型。ref() 接收参数,并将其包裹在一个带有 .value 属性的 ref 对象中返回。

在js代码中需要通过ref对象的.value属性,然后再得到具体的内容进行赋值和使用,在template中可以直接使用,不需要进行.value操作。

reactive说明:

reactive() 返回的是一个原始对象的 Proxy,只有代理对象是响应式的,更改原始对象不会触发更新。使用 Vue 的响应式系统的最佳实践是 仅使用你声明对象的代理版本

有限的值类型:它只能用于对象类型 (对象、数组和如 MapSet 这样的集合类型)。它不能持有如 stringnumberboolean 这样的原始类型。

不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象。

对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接。

由于这些限制,我们建议使用 ref() 作为声明响应式状态的主要 API。

3.reactive响应式失效问题

1.reactive声明对象没有失效

<template><div id="count1">count值: {{ count }}</div><div><div>姓名:{{ student.name }}</div><div id="stu1">点赞数:{{ student.num }}</div></div><div><button @click="btnClick()">按钮</button></div>
</template>
<script setup>
import { ref, reactive } from 'vue';
const count = ref(0);
let student = reactive({name: '小李',num: 0
})const btnClick = () => {count.value++;student = reactive({name: '小孙',num: 1})
}
</script>

点击按钮前:

点击按钮后:

可以看到值已经发生变化。

2.reactive声明数组响应式失效。

<template>
<div>{{ list }}
</div>
<div><button  @click="btnClick()">按钮</button>
</div></template><script setup>import {reactive} from 'vue';let list = reactive(['123','234','345'
])
const btnClick = () =>{list = ['258','369','147'];console.log(list);
}
</script>

按钮点击前:

按钮点击后:

点击按钮后,list的值如控制台已经发生了变化,但是视图已经渲染,但是内容没有更新。此种方式不会触发视图更新,因为地址指向变成了一个新的地址。

解决方法:

①使用ref进行定义。将对象的.value设定为新的数组。

②将数组用对象的方式进行包裹,给对象中的属性进行赋值,在template中使用对象中的属性进行显示。如下:

<template>
<div>{{ list.arr }}
</div>
<div><button  @click="btnClick()">按钮</button>
</div></template><script setup>import {ref,reactive} from 'vue';let list = reactive({arr:['123','234','345'
]
})
const btnClick = () =>{list.arr = ['258','369','147'];console.log(list);
}
</script>

③采用push方式进行更新,注意要使用扩展运算符,否则会在数组中嵌套一个数据。

<template><div>{{ list }}</div><div><button @click="btnClick()">按钮</button></div>
</template><script setup>import { ref, reactive } from 'vue';let list = reactive(['123', '234', '345'
]
)
const btnClick = () => {list.push(...['258', '369', '147']);console.log(list);
}
</script>

 在使用reactive时需要使用const方式进行定义。通过const定义只能修改对象中属性,而不能修改整个对象。

4.总结

关于ref及reactive的用法,还是要在开发中多多使用,遇到响应式失效问题,仔细研究,加强理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud:Eureka

目录 一、Eureka介绍 1.Eureka的作用 2.总结 二.搭建Eureka服务端步骤 1.导入maven依赖 2.编写启动类&#xff0c;添加EnableEurekaServer注解 3.添加application.yml文件&#xff0c;编写下面的配置&#xff1a; 三.注册Eureka客户端服务提供者&#xff08;user-servic…

【每日OJ—有效的括号(栈)】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 1、有效的括号题目&#xff1a; 1.1方法讲解&#xff1a; 1.2代码实现&#xff1a; 总结 前言 世上有两种耀眼的光芒&#xff0c;一种是正在升起的太阳&#…

系统架构设计师教程(五)软件工程基础知识

软件工程基础知识 5.1 软件工程5.1.1 软件工程定义5.1.2 软件过程模型5.1.3 敏捷模型敏捷开发的特点敏捷方法的核心思想主要敏捷方法简介 5.1.4 统一过程模型 (RUP)RUP的生命周期RUP中的核心概念RUP的特点 5.1.5 软件能力成熟度模型 5.2 需求工程5.2.1 需求获取需求获取的基本步…

CAN静默回环模式测试

本文章主要用于 看自己写的CAN协议代码是否正确 然后因为只有一块板子&#xff0c;不能通信的情况 can.h #ifndef __CAN_H #define __CAN_H#include "head.h"extern FlagStatus can0_receive_flag; extern FlagStatus can0_error_flag; extern can_trasnmit_messag…

HashMap扩容机制详解

目录 1. 扩容的触发条件 2. 扩容的具体步骤 2.1 计算新的容量 2.2 创建新的桶数组 2.3 将元素重新分配到新的桶数组中 2.4 更新容量和阈值 3. 与并发性能的关系 4. 扩容的性能优化 5. 总结 HashMap是Java中常用的数据结构之一&#xff0c;用于存储键值对。在HashMap内…

Electron 打开开发者工具 devtools

Electron 打开开发者工具 devtools 在electron开发的过程中&#xff0c;可以用代码控制打开自带chrome的devtools开发者工具&#xff0c;进而调试渲染教程页面。 平时&#xff0c;我们利用chrome要调试网页的时候&#xff0c;按F12&#xff08;mac下面是shift花i&#xff09;…

sql 数据类型注入+tamper

数据类型 数字型 0-9 查询语句&#xff1a; $sql"select * from sy_guestbook where id$i"; 字符型 a-z 中文 标点符号 加入了单引号 查询语句&#xff1a; $sql"select * from sy_guestbook where gTpl$g"; simple order by 16--select * from sy_g…

物联网在能源管理中的应用——青创智通工业物联网解决方案

随着全球能源资源的日益紧张和环境问题的日益突出&#xff0c;能源管理已成为当今社会的重要议题。物联网技术的快速发展为能源管理提供了新的解决方案。本文将介绍物联网在能源管理中的应用及其优势。 一、物联网在能源管理中的应用 1. 智能电网 智能电网是物联网在能源管理中…

vue 高频面试题

vue 高频面试题 0.那你能讲一讲MVVM吗&#xff1f; MVVM是Model-View-ViewModel缩写&#xff0c;也就是把MVC中的Controller演变成ViewModel。Model层代表数据模型&#xff0c;View代表UI组件&#xff0c;ViewModel是View和Model层的桥梁&#xff0c;数据会绑定到viewModel层…

Android 生物识别:构建一个存储用户敏感信息的安全应用

前言 在当今数字时代&#xff0c;随着科技的不断发展&#xff0c;用户敏感信息尤为重要。从指纹到面部识别&#xff0c;再到虹膜扫描&#xff0c;生物识别技术为我们带来了便捷性和安全性。本次将构建一个简易的账户信息应用&#xff0c;运用生物识别技术来提高信息的安全性。…

数据结构之预习作业:排序(v1)

看视频&#xff0c;回答以下问题&#xff1a; 1.系统提到了哪些排序场景&#xff1f;除此之外&#xff0c;你还知道哪些信息系统有排序&#xff1f; 2.什么样的排序方法是稳定的&#xff1f;请举例说明 3.插入类排序分为哪几类&#xff1f; 4.若对n个元素进行直接插入排序&…

C++ 单词替换

输入一个字符串&#xff0c;以回车结束&#xff08;字符串长度不超过 100 &#xff09;。 该字符串由若干个单词组成&#xff0c;单词之间用一个空格隔开&#xff0c;所有单词区分大小写。 现需要将其中的某个单词替换成另一个单词&#xff0c;并输出替换之后的字符串。 输入…

使用Java实现简单的网络爬虫,并使用代理IP

目录 前言 一、了解网络爬虫的基本原理与流程 二、选择合适的技术与工具 三、编写代码实现网络爬虫 四、解析网页内容 总结 前言 网络爬虫是一种自动化程序&#xff0c;用于从互联网上抓取信息。它可以帮助我们快速地获取大量数据&#xff0c;并进行分析和处理。在实际应…

滑动窗口(一)

滑动窗口 什么是滑动窗口算法&#xff1f;通俗的来讲就是 “同向双指针” &#xff0c;当一组数据的规律含有单调性的时候&#xff0c;就可以使用下面这套逻辑来优化暴力解法。 当两个指针同向移动的时候&#xff0c;类似于一个窗口在滑动。使用于在连续序列里找特殊的子串、…

在centos7上安装docker

1.CentOS安装Docker Docker CE 支持 64 位版本 CentOS 7&#xff0c;并且要求内核版本不低于 3.10&#xff0c; CentOS 7 满足最低内核的要求&#xff0c;所以我们在CentOS 7安装Docker。 1.1.卸载&#xff08;可选&#xff09; 如果之前安装过旧版本的Docker&#xff0c;可…

C语言之递归函数

目录 函数和类型 阶乘 █递归函数调用 函数中可以调用和该函数自身完全相同的函数&#xff0c;这样的调用方式称为递归函数调用&#xff0c;下面我们就来学习相关的基础知识。 函数和类型 所谓递归&#xff08;recursive&#xff09;&#xff0c;就是将自己包含在内&#x…

ubuntu添加路由

ip route show 查看当前路由表 sudo ip route add /mask via 添加一条路由 目标ip 1.1.1.1/100 下一跳 2.2.2.2 sudo ip route add 1.1.1.1/100 via 2.2.2.2 dev ens160 proto static metric 100这是一条Linux命令&#xff0c;用于添加一个静态路由。具体含义如下&#xff1…

AI 绘画 | Stable Diffusion 视频数字人

前言 本篇文章教会你如何利用Stable Diffusion WEB UI,使用一个人物图片转换成为一个口播视频。本篇内容的教程以WINDOWS系统为例,教你如何安装使用。 先看视频效果 彭于晏图片生成口播视频 安装 首先需要在windows电脑上安装ffmpeg,按照本教程《在 Windows PC 上轻松下载并…

DataGrip 2023.3 新功能速递!

1 数据可视化 自 DataGrip 2023.3 发布以来&#xff0c;已整合 Lets-Plot 库&#xff0c;实现数据可视化。该可视化功能可用于所有三种类型的网格&#xff1a; 主选项卡&#xff1a;在打开表、视图或 CSV 文件时&#xff0c;在分割模式下显示图表。结果选项卡&#xff1a;在 服…

centos安装opencv并在springboot中使用

使用conda安装opencv&#xff0c;并在docker运行的容器中使用&#xff0c;这里以运行则springboot应用的容器为例 步骤一&#xff1a;安装 在conda中安装 # 安装依赖 conda install numpy matplotlib# 安装opencv conda install -c conda-forge opencv # 或者制定版本 conda…