Vue3 reactive丢失响应式问题

2023-11-11

问题描述:使用 reactive 定义的对象,重新赋值后失去了响应式,改变值视图不会发生变化。

测试代码:

<template>
    <div>
        <p>{{ title }}</p>
        <ul>
            <li v-for="(item, index) in tableData" :key="index">{{ item }}</li>
        </ul>
    </div>
</template>

<script setup>
    import { ref, reactive, onMounted } from 'vue'
    
    const title = ref('我是标题')
    let tableData = reactive([1, 2, 3])

    onMounted(() => {
        title.value = '我是段落',
        tableData = [1, 1, 1]
        console.log("title=", title)
        console.log("tableData=", tableData)
    })    
</script>

输出结果:

 

从上述测试代码中,ref 定义的对象有响应式,而 reactive 定义的对象失去了响应式,这是什么原因呢?官网中写到:

如果将一个对象赋值给 ref ,那么这个对象将通过 reactive() 转为具有深层次响应式的对象。

那么,为什么 ref 调用 reactive 处理对象重新赋值后,不会丢失响应式,但 reactive 却丢失了呢?

第一步:当我们修改 xxx.value 值的时候,setter 调用了 toReactive 方法

class RefImpl {
    constructor(value, __v_isShallow) {
        this.__v_isShallow = __v_isShallow;
        this.dep = undefined;
        this.__v_isRef = true;
        this._rawValue = __v_isShallow ? value : toRaw(value);
        this._value = __v_isShallow ? value : toReactive(value);
    }
    get value() {
        trackRefValue(this);
        return this._value; // get方法返回的是_value的值
    }
    set value(newVal) {
        newVal = this.__v_isShallow ? newVal : toRaw(newVal);
        if (hasChanged(newVal, this._rawValue)) {
            this._rawValue = newVal;
            this._value = this.__v_isShallow ? newVal : toReactive(newVal); // set方法调用 toReactive 方法
            triggerRefValue(this, newVal);
        }
    }
}

 第二步:toReactive 方法判断是否是对象,是的话就调用 reactive 方法

const toReactive = (value) => isObject(value) ? reactive(value) : value;

 第三步:reactive 方法,先判断数据是否是“只读”的,不是就返回 createReactiveObject() 方法处理后的数据(createReactiveObject 方法将对象通过 proxy 处理为响应式对象)

function reactive(target) {
    // if trying to observe a readonly proxy, return the readonly version.
    if (isReadonly(target)) {
        return target;
    }
    return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
}

结论:

ref 定义数据(包括对象)时,都会变成 RefImpl(Ref 引用对象) 类的实例,无论是修改还是重新赋值都会调用 setter,都会经过 reactive 方法处理为响应式对象。
但是 reactive 定义数据(必须是对象),是直接调用 reactive 方法处理成响应式对象。如果重新赋值,就会丢失原来响应式对象的引用地址,变成一个新的引用地址,这个新的引用地址指向的对象是没有经过 reactive 方法处理的,所以是一个普通对象,而不是响应式对象。

如何正确使用 reactive 呢?

使用 reactive 定义数据时,使用对象包含键值对的形式,那么就会避免重新赋值的问题。那么,修改测试代码为:

<template>
    <div>
        <p>{{ title }}</p>
        <ul>
            <li v-for="(item, index) in obj.tableData" :key="index">{{ item }}</li>
        </ul>
    </div>
</template>

<script setup>
    import { ref, reactive, onMounted } from 'vue'
    
    const title = ref('我是标题')
    let obj = reactive({
        tableData: [1, 2, 3]
    })

    onMounted(() => {
        title.value = '我是段落',
        obj.tableData = [1, 1, 1]
    })    
</script>

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue3 reactive丢失响应式问题 的相关文章

  • chrome 调试器承诺在暂停时不会解析?

    也许我没有正确调试承诺 但基本上 如果您在断点处停止并运行异步代码 它实际上不会完成 直到您恢复执行为止 这是一个问题 调试器允许您快速试验多个 api 方法 但如果您恢复它 您就不能 debugger now type the follo
  • 动态速度计 javascript 或 jquery 插件

    我希望有动态ajax插件在页面上显示速度计 一个想法是我设置一个背景并旋转针 有人知道相关插件吗 这里有一些供您参考 http bernii github com gauge js http bernii github com gauge
  • Node js 使用中间件重定向进行过多重定向

    在我的 Node js 应用程序 我使用的是express 4 x 中 我想检查用户是否已登录 如果用户未登录 我想重定向到我的登录页面 然后我在中间件中这样做 服务器 js app use function req res next if
  • Leaflet js虚构地图

    我是 Leaflet 的新手 我想了解如何创建完全交互式的虚构地图 我有一张图像想要转换为传单地图 该图像基本上像图表一样具有许多连接和点 我想首先将该图像转换为地图 能够将鼠标悬停在这些点上 突出显示它们并显示有关它们的信息 并且还可以在
  • 使用 CryptoJS 更改密钥 [重复]

    这个问题在这里已经有答案了 我正在使用 CryptoJS 来加密和解密文本 在这里 我只是获取消息并显示加密和解密消息 我使用DES算法进行加密和解密 这是我的 HTML 文件
  • Node.js - console.log 不显示数组中的项目,而是显示 [Object]

    我在注销对象内数组的内容时遇到问题 实际的物体看起来像这样 var stuff accepted item1 item2 rejected response Foo envelope from The sender to new item1
  • 在闪亮的数据表中为每个单元格显示工具提示或弹出窗口?

    有没有什么方法可以为 r闪亮数据表中的每个单元格获取工具提示 有很多方法可以获取悬停行或列 但我找不到一种方法来获取行和列索引并为每个单元格显示不同的悬停工具提示 任何人都可以修改以下代码吗 library shiny library DT
  • Typeahead.js substringMatcher 函数说明

    我只是在做一些研究Typeahead js这是一个非常酷的图书馆 感谢文档 我已经成功地获得了一个基本的示例 该文档也非常好 但是我试图弄清楚以下代码块实际上在做什么 var substringMatcher function strs r
  • 使用 JS 合并具有相同值的相邻 HTML 表格单元格

    我已经为此苦苦挣扎了一段时间 我有一个根据一些 JSON 数据自动生成的表 该数据可能会有所不同 我想合并第一列中具有相同值的相邻单元格 例如此表中的 鱼 和 鸟 table tr td fish td td salmon td tr tr
  • JS用正则表达式替换数字

    我有元素的标识符 如下所示 form book 1 2 3 我想要的是用其他值替换该标识符中的第二个数字 我将函数 match 与以下正则表达式一起使用 var regexp d d d 但它返回我包含的数组 1 2 3 2 因此 当我尝试
  • IE11不监听MSFullscreenChange事件

    我正在尝试使用 Bigscreen js 在 IE11 中使用全屏 但 IE11 不监听 MS FullscreenChange 事件 document addEventListener MSFullscreenChange functio
  • 单击关闭按钮后不显示 Google 一键登录 UI

    我正在尝试按照本指南使新的谷歌一键登录工作 https developers google com identity one tap web https developers google com identity one tap web
  • 将 javascript 整数转换为字节数组并返回

    function intFromBytes x var val 0 for var i 0 i lt x length i val x i if i lt x length 1 val val lt lt 8 return val func
  • Twitter 嵌入时间轴小部件

    我继续下载http platform twitter com widgets js http platform twitter com widgets js And the http platform twitter com embed t
  • 为什么“tbody”不设置表格的背景颜色?

    我在用 tbody 作为 CSS 选择器来设置background color在一个表中 我这样做是因为我有多个 tbody 表内的部分 它们具有不同的背景颜色 我的问题是 当使用border radius在细胞上 细胞不尊重backgro
  • 查询为空 Node Js Sequelize

    我正在尝试更新 Node js 应用程序中的数据 我和邮递员测试过 我的开发步骤是 从数据库 MySQL 获取ID为10的数据进行更新 gt gt 未处理的拒绝SequelizeDatabaseError 查询为空 我认识到 我使用了错误的
  • Select2 下拉列表动态添加、删除和刷新项目

    这让我发疯 为什么 Select2 不能在其页面上实现清晰的方法或示例如何在 Select2 上进行简单的 CRUD 操作 我有一个 select2 从 ajax 调用获取数据
  • 如果数字小于 10,则显示前导零 [重复]

    这个问题在这里已经有答案了 可能的重复 JavaScript 相当于 printf string format https stackoverflow com questions 610406 javascript equivalent t
  • 防止文本区域出现新行

    我正在开发聊天功能 使用 Vue 并使用文本区域作为输入 以便溢出换行 并且对于编写较长消息的用户来说更具可读性 不幸的是 当用户按下 Enter 键并提交时 光标会在提交之前移动到新行 从而使用户体验感觉不佳 关于如何使用普通 Javas
  • 用于 C# XNA 的 Javascript(或类似)游戏脚本

    最近我准备用 XNA C 开发另一个游戏 上次我在 XNA C 中开发游戏时 遇到了必须向游戏中添加地图和可自定义数据的问题 每次我想添加新内容或更改游戏角色的某些值或其他内容时 我都必须重建整个游戏或其他内容 这可能需要相当长的时间 有没

随机推荐

  • C# => Lambda表达式理解

    本文参考网上的博客和找到的资料加上个人理解编写的 主要的代码借鉴 http www cnblogs com knowledgesea p 3163725 html 百度百科 希望能够帮助理解lambda表达式 定义 Lambda表达式 是一
  • 阿里测开的性能测试技术笔记:如何快速上手压测工作

    新年第一个工作日 继续整理之前的技术笔记 前面通过三篇的内容 将自动化测试相关的技术笔记做了整理汇总 这篇内容 主要是我刚开始做性能测试时的一些记录 对新手或者刚进入一个新项目的同学 应该有所帮助 一般我们在刚介入一个项目时 我认为可以从如
  • 基于视觉重定位的室内AR导航APP的大创项目思路(3)手机相机内参数据获取和相机标定

    文章目录 相机内参 为什么要获取相机的内参数据 获取相机内存数据的方法 棋盘格标定 自动相机标定 前情提要 是第一次做项目的小白 文章内的资料介绍如有错误 请多包含 相机内参 相机内参是本身的物理数据 包括焦距f和缩放c 一般以矩阵K的形式
  • Lattice Diamond 3.12下载与安装(免费获取license.dat)

    Lattice Diamond 3 12下载 安装与激活 免费获取license dat Lattice Diamond是LATTICE半导体公司推出的一款免费的FPGA开发软件 其实这个软件具体的下载与安装过程在其配套文档里有比较详细的说
  • STM32Cube MX USB双设备MSC+CDC 实现虚拟U盘+虚拟串口

    前言 在上一篇文章实现USB虚拟U盘之后 项目需要用同一个USB口同时实现MSC和CDC功能 既能进行串口通信又能读取片外FLASH虚拟U盘 对于USB通用串行总线如果要真正搞明白这个协议还是比较困难的 需要用不少时间来了解驱动原代码 但是
  • IDA动态调试动态注册native函数流程

    安卓 手游逆向交流群963612891 IDA动态调试动态注册native函数流程1 编写目的 记录IDA动态调试步骤 2使用工具 逆向工具 IDA 7 0 Jadx 运行环境 Nexus 5 Android 4 4 3 原字符串信息 4
  • Vue - 使用Lodash进行深拷贝

    文章目录 深浅拷贝的理解 使用lodash 深浅拷贝的理解 浅拷贝 只是将数据中所有的数据引用下来 依旧指向同一个存放地址 拷贝之后的数据修改之后 也会影响到原数据的中的对象数据 例如 Object assign 扩展运算符 深拷贝 将数据
  • 利用xpath解析器爬取豆瓣电影top250

    首先声明需要用的库 当然我还用到了os库 将工作路径修改到了我指定的路径 os chdir r C Users from lxml import etree import requests import time import json 豆
  • 潘建伟在量子纠缠领域获新突破;特斯拉起诉小米持股公司;WPS AI面向社会开放;腾讯或将发布混元大模型丨每日大事件...

    大数据产业创新服务媒体 聚焦数据 改变商业 企业动态 TikTok在爱尔兰开设数据中心 TikTok 9月5日发布声明 宣布位于爱尔兰都柏林的首个数据中心现已投入运营 开始向该中心迁移欧洲用户数据 TikTok表示 位于挪威和爱尔兰的另外两
  • PyCharm入门教程——自动导入(下)

    查看 PyCharm入门教程 自动导入 上 PyCharm 是一种Python IDE 其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具 此外 该IDE提供了一些高级功能 以用于Django框架下的专业Web开发 PyC
  • 面试过程中应注意的问题与禁忌

    面试过程中应注意的问题与禁忌 一 面试中应注意的问题 应试者要想在面试答辩中获得成功 必须注意以下几个问题 一 淡化面试的成败意识 一位面试者在面试前自认为各方面都比别人优秀 因此 他认为自己可以高枕无忧了 谁知主考官在面试中出其不意 提了
  • layui日期多选

    先引入layui的css和js html部分 div class layui inline div
  • Eclipse快捷键的使用

    ctrl 2 L这个快捷键可自动补全代码 极大提升编码效率 注 ctrl和2同时按完以后释放 再快速按L ctrl 1提示快捷键 能快速的实现光标所在行的问题 并给出一些修改方案 按键盘上的ALT 方向键 或者 就能上下移动
  • 【路径规划】基于前向动态规划算法在地形上找到最佳路径(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 汽车必须尽可能靠近目标坐标 旅行时间应尽可
  • Pycharm连接远端服务器配置【保姆级教程】

    提示 需要提前安装Pycharm专业版 可以用破解版或者学生认证一年试用期 网上有教程 文章目录 前言 软硬件环境 一 配置SSH连接服务器 1 立马遇到bug 没有出现以下问题可以跳过 2 配置本地与服务器文件同步 3 同步代码到服务器上
  • React基础教程(二):React的基本使用

    React基础教程 二 React的基本使用 1 HelloReact 1 1 引入react基础依赖包 注意点 必须要在 之前引入
  • 利用unordered_map特性求交集

    unordered map 是关联容器 含有带唯一键的键 值 pair 搜索 插入和元素移除拥有平均常数时间复杂度 元素在内部不以任何特定顺序排序 而是组织进桶中 元素放进哪个桶完全依赖于其键的哈希 这允许对单独元素的快速访问 因为一旦计算
  • 什么是Three.js?(一)

    Three js是一款运行在浏览器中的 3D 引擎 基于WebGL的API的封装 你可以用它来创造你所需要的一系列3D动画场景 如最近比较火的在线试衣间 医疗设备可视化等等 如果你第一次接触Three js 那么就跟着我们的文章一起学习就好
  • VSCode手记

    设置为中文 如何将VSCode设置成中文语言环境 vscode设置中文 z975821109的博客 CSDN博客 快捷键 跳转声明代码 F12 撤销 Ctrl Z 重做 Ctrl Y 查找 Ctrl F 删除当前行 Ctrl Shift K
  • Vue3 reactive丢失响应式问题

    问题描述 使用 reactive 定义的对象 重新赋值后失去了响应式 改变值视图不会发生变化 测试代码