Vue3 Ref 对象无法重置的问题

问题记录

这里进行一个简单的记录。
今天发现一个小问题,在使用 ref 创建对象的对象无法重置为初始值。用了 kimi 和 deepseek 也没解决这个问题。最后灵光一闪,问题解决了
先看一下有问题的代码

const initPageInfo = {
  pageNo: 1,
  pageSize: 10,
  total: 0,
}
const pageInfoRef = ref(initPageInfo)

在上面代码中进行了简单一个分页信息保存。在某些条件下,我希望重置这个分页信息,于是我尝试了以下的操作

pageInfoRef.value = {...initPageInfo}

原本以为这样就可以了,可是万万没想到,分页其实并没有被重置。于是我拿着我的信息问了 kimi 和 deepseek。他们告诉我要这么做

Object.assign(pageInfoRef.value, initPageInfo)

甚至还有更神的操作

pageInfoRef.value = JSON.parse(JSON.stringify(initPageInfo))

我尝试了他们说的第一个方案,没有效果。第二个神操作我没有试,但是我感觉应该不可以

解决方案

后来我忽然灵光一闪,下面是解决方案
在第一次对 pageInfoRef 进行初始化的时候需要更改一下方案

const pageInfoRef = ref({...initPageInfo})

原因分析(查看下面更新的内容)

这里我并没有分析出来具体的原因,可能与 ref 创建响应式对象的方式有一定的关系。
因为我在测试的过程中还尝试下面的方式,它是却是能进行正常响应式的。
我不理解这种原始的方式创建的对象和解构赋值得到的对象 {...initPageInfo} 是不是有什么本质的不同,导致 vue 不能正确的帮我创建响应式对象。或许需要看一下 vue 的相关文档或者是看一下相关源码了。暂时没有时间去深究这个问题。

pageInfoRef.value = {
  pageNo: 1,
  pageSize: 10,
  total: 0,
}

2025年7月10日 更新

今日得闲,看了一下这个文章。找到了原因

直接使用

const pageInfoRef = ref(initPageInfo)

vue 会把 initPageInfo 这个对象变成响应式对象。

所以在后续中使用下面两种方式,看上去似乎没有改变 pageInfoRef,实际上是已经改变了。只是因为 initPageInfo 的内容已经被 pageInfoRef.value 修改过,所以只要是使用 initPageInfo 去修改 pageInfoRef.value 不论如何,都是无法回归初始值的

pageInfoRef.value = {...initPageInfo}
pageInfoRef.value = JSON.parse(JSON.stringify(initPageInfo))

验证方法

<script setup>
import { ref } from 'vue'

const initPageInfo = {
  pageNo: 1,
  pageSize: 10,
  total: 0,
}
const pageInfoRef = ref(initPageInfo)

const changePage = (no) => {
  pageInfoRef.value.pageNo = no
  
  console.log(initPageInfo)
}
</script>

<template>
  <div>
    <p>pageNo: {{ pageInfoRef.pageNo }}</p>
  </div>
  <button @click="changePage(++pageInfoRef.pageNo)">下一页</button>
  <button @click="changePage(--pageInfoRef.pageNo)">上一页</button>
</template>

<style scoped>

我在 changePage 函数中打印了 initPageInfo,会发现每次点上一页或者下一页的时候,都会改变 initPageInfo 这个对象的值

所以如果初始化 ref 的时候如果想让 pageInfoRef 还能被重置,那么在初始化的时候就要初始化一个完全脱离原来的引用对象。
比如使用 const pageInfoRef = ref({...initPageInfo}) 如此就可以让这个 pageInfoRef 响应式对象能被重置了

不过需要注意, {...initPageInfo} 只能处理简单的对象,如果是要处理复杂对象,就需要深度克隆。或者把 initPageInfo 变成一个函数,调用时返回出一个新对象即可

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容