vue3.0+vite+store 变量赋值问题?

今天用vue3+vite+store想要完成一个单处变更至全局动态变化的问题,但是遇到了一个很奇怪的现象,我大致知道可能是内置变量机制的问题,但是请教大神告知深层次的原因

版本如下
image.png

功能描述大概就是,左侧树节点点击后会触发修改

//节点点击触发事件
const toggleNodeChoosed=(clicked)=>{
  clicked.choosed=!clicked.choosed;
  let savedposts = store.getters.getChoosedDeptPost;//从store获取选数据
  if(!savedposts){
    savedposts=[]
  }
  // 如果我对该值进行深拷贝,则功能无效,注释掉本行之后功能正常
  // savedposts=JSON.parse(JSON.stringify(savedposts));
  console.log("11111111",savedposts)
  if(!clicked.choosed){
    while(savedposts.some((item)=>item.postcode===clicked.code)){
      savedposts.forEach((item,index)=>{
        if(item.postcode==clicked.code){
          savedposts.splice(index,1)
        }
      })
    }
  }else if(clicked.choosed){
    let {code,name}=clicked; 
    savedposts.push({code,name});
  }
  store.commit("setChoosedDeptPost",savedposts)
};

image.png

不进行深拷贝控制台打印如下

image.png

进行深拷贝后页面渲染及控制台打印如下

image.png

不是说深拷贝是该方法必须,而是一个现象提取;更直观的原因是我不能对store.getters.getChoosedDeptPost获得的数组进行存储域重定向,即不能重新赋值代码中的“savedposts”,即只能变更原数组,类似于filter过滤等重新赋值操作都不能。也不是说非要用重新复制的方法去做,只是想知道不能的底层逻辑是什么,请各位大佬萌新小可爱程序员程序猿们帮忙解答,靴靴~

阅读 1.1k
2 个回答

有点没看明白,不过大概猜测是和你给对象的赋值操作相关。因为当你将一个新的对象赋值给 savedposts 这个变量,那么变量 savedposts 将指向新对象的内存地址,而不是原来的内存地址了。即你说的只能变更原数组,类似于filter过滤等重新赋值操作都不能。

具体可以参考我在这个问答中的一些举例说明 👉 为什么new Map也被垃圾回收了?
可能会帮助你理解引用关系方面的一些疑惑。


所以一般来说我们并不会在外部直接操作 Vuexstate 值,通过 commit 去提交 Mutations 中的修改操作给 Vuex 来处理。
以及获取 state 的时候会通过 mapState 或者 mapGetters 来获取,而不是直接 store.state.xxx 这样了获取,以避免直接修改 state


另外,你是使用 JSON.parse(JSON.stringify(savedposts)) 这样取巧的方式来实现的深拷贝。“拷贝”出来的结果会丢失很多的信息,比如说:

  1. 无法复制函数:如果对象中包含函数,那么该函数将不会被复制。
  2. 无法复制循环引用的对象:如果对象中存在循环引用,例如对象 a 的属性 b 指向 a,那么这种方式将会抛出错误。
  3. 无法复制特殊的对象:像 DateRegExpMapSet 等特殊对象在序列化后,不能恢复为原来的对象。
  4. 无法复制 undefined:如果对象中的某个属性值为 undefined,那么这个属性将不会被复制。

这块内容可能你自己做一下手写深拷贝函数会理解的更好一些。

Vue3 建议搭配 pinia,composition API 的写法更清晰明了。

推荐问题
宣传栏