vuex中数据动态添加属性响应式丢失

460 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情

起因

搞某个电商项目,要在购物车里添加商品。然后首先有一个商品列表。都放在了store里,shoppingCart里面存放商品id,值就是商品在购物车的数量。

store={
  caiList:[{name:'茄子',id:'1',img:"qiezi.png"},{name:'黄瓜',id:'2',img:"huanggua.png"}],
  shoppingCart:{}
}

然后在组件里获取商品caiList。然后遍历渲染。caiList在组件里是通过正当手段获取的,不会报错,忽略存在的问题。

<template>
  <div>
      <h1>菜品</h1>
      <div v-for='(item) in cailist'>
          <img :src="item.img" />
          <button @click='add(item.id)'>添加</button>
      </div>
  </div>
</template>

假设上面组件里写了正确的方法,方法里直接执行store.commit('ADD',item.id);就是触发了一个mutation,然后假设mutation里面也写了对应的方法。大概意思就是如果购物车里有这个种类的商品,那么就在当前数量的基础上加一,否则就是第一次加,从0到1,直接赋值为1,简直是没毛病,

mutations:{
  ADD(store,payload){
     store.shoppingCart[payload]=store.shoppingCart[payload]?++store.shoppingCart[payload]:1
  }
}

实验是检验真理的唯一标准,然后测试,添加添加再添加,添加了半天,页面上用的shoppingCart地方也没有变化,这是因为shoppingCart原来没有属性。这个是动态属性。和vue动态添加属性一样,因为数据初始化的时候会遍历嘟对象的属性添加get和set劫持,但是对于新添加的属性,vue2并不能自动响应,如果是vue可以解决这个问题,因为vue3是proxy, 那么vue2中就整不了吗?不是的。可以像组件中设置动态方法一样,使用Vue.set(对象,属性,值)

mutations:{
  ADD(store,payload){
     if(store.shoppingCart[payload]){
     store.shoppingCart[payload]++
     }else{
     Vue.set(store.shoppingCart,payload,1)
     }
  }
}

当然也可以赋值一个新的对象。

mutations:{
  ADD(store,payload){
     if(store.shoppingCart[payload]){
      store.shoppingCart[payload]++
     }else{
     store.shoppingCart={
       ...stroe.shoppingCart,
       [payload]:1
     }
     }
  }
}

删除也是同样的道理

mutations:{
  SUB(store,payload){
     if(store.shoppingCart[payload]>1){
      store.shoppingCart[payload]--
     }else{
     Vue.delet(store.shoppingCart,payload)
     }
  }
}

vue2使用起来确实有些不方便,但是vue3上手后就变得丝滑很多,业内的内卷导致框架精益求精,vue和react还是要相互结合,搞一个更好。