购物车:全选 全不选 单选 计算总价和件数(vuex 中用到:state, mutations,getters, actions) (难ε=(´ο`*)))唉)

559 阅读2分钟

思路:

前端:

  1. 将后端返回的数组 通过循环,将数组的每个对象 都添加一个属性 checked 默认为 true

  2. 前端渲染的时候,就可以直接把 第一步添加的 checked属性 动态绑定到 对应的选项标签上

  3. 在vuex中 分别写:全选 全不选 单选 逻辑

    3.1 首先准备2个数组,第一个是 后端返回的数据 list ,第二个数组 自己定义一个空数组

    state: {
     list: [], // 购物车数据
     selectList: [] // 被选中的数据 id
     },
    

    3.2 mutations中 初始化的时候,将通过map 将被选中的数据 id 拷贝一份进入到定义的空数组里

      mutations: {
         [CART_DATA](state, data) {
             state.list = data
             // 初始化的时候,将id 通过map复制到 新的组数中,解决这个问题:如果用forEach(),会有每次进到购物车页面,都循环push id进去 导致全选按钮没有默认选中的问题,就是getters中的两个数组长度不一样了。所以换成了 map
              state.selectList = data.map(v => {
                 return v.id
             })
             console.log(state.list, state.selectList);
         },
        }
        
    

    3.3 开始做全选功能:也是循环遍历后端返回的数组,将遍历的项的 v.checked = true; 最后赋值给 自定定义的数组,

      // 全选
      [CHECK_ALL](state) {
         state.selectList = state.list.map(v => {
             v.checked = true;
             return v.id
         })
     },
     
    

    3.4 全不选功能:也是循环遍历后端返回的数组,将遍历的项的 v.checked = false; 将自定义的数组 赋值为 空数组 state.selectList = []

    // 全不选
      [UNCHECK_ALL](state) {
         state.list.map(v => {
             v.checked = false;
             return v.id
         })
         state.selectList = []
     },
     
    

    3.5 单选 根据 后端返回数组的下标id ,去 第二个数组中查找对应的内容,如果找到就删除,找不到 就添加 这个方法的index 是通过绑定在vue组件单选按钮上传递过来的 index值,其实有点绕 有点难,对新手来说

      [CHECK_ITEM](state, index) {
         // console.log(state.list[index].id, state.selectList);
         let indexId = state.list[index].id
         let i = state.selectList.indexOf(indexId)
         // console.log(i, "77");
         if (i > -1) {
             // 可以找到 把当前这个删掉
             return state.selectList.splice(i, 1)
         }
         // 如果之前没有选中 ,就将当前的id push进去
         state.selectList.push(indexId)
         console.log(state.list.length, state.selectList.length);
     },
    

    3.5 判断2个数组的length是否相等 如果相等 就在actions 提交commit mutations中的全选 或 全不选

    getters: {
         // 判断2个数组的length是否相等
         isCheckedAll(state) {
             return state.list.length == state.selectList.length
         }
     },
     
     
     
    

    3.6 在actions 提交commit mutations中的全选 或 全不选

     actions: {
         checkAllFn({commit, getters }) {
             getters.isCheckedAll ? commit("unCheckAll") : commit("checkAll")
         }
     }
    
  4. 在getters中计算单价和 总数 ,注意判断 当都是选中状态的时候 才计算

      // 计算数量
     total(state) {
         let total = {
             num: 0,
             price: 0
         }
         state.list.forEach(v => {
             console.log(v);
             if (v.checked) { 
                 total.num += parseInt(v.num)
                 total.price += v.shop_price * v.num
             }
         })
         return total
     }
    

问题:

vue组件 这里绑定数据用的数 v-module 双向数据流,但是 vuex的数据 是单向数据流,

视图错误 image.png

在vue组件中引入vuex的内容:

image.png

在vue组件中v-module 使用: image.png

解决办法参考:segmentfault.com/a/119000001…

解决方法一(失败了,后面有机会回头再看吧,先用方法二):将 ...mapGetters(["isCheckedAll"]), 替换成下面的方式, 然后也可以使用v-model来绑定数据

 // ...mapGetters(["isCheckedAll"]),
    isCheckedAll: {
      get() {
        return this.$store.getters.isCheckedAll;
      },
      set(val) {
        return (this.$store.getters.isCheckedAll = val);
      },
    },

解决办法二:将v-model 改成 :value 还是使用: ...mapGetters(["isCheckedAll"])

<van-checkbox @click="checkAllFn" :value="isCheckedAll">

功能如图:

image.png