vue实现购物车页面操作 商品的单选和全选以及商品单价和总价的动态变化

vue框架搭建,UI库使用的是iview,购物车页面使用iview的table组件,没有用到element,不知道实现起来效果怎么样,感觉iview有点坑。

准备工作:
  • 数据源
    shoppingCart:[ ];
    该数据数据结构如下
const items = {
        id: data.id,
        num: data.num,
        img: data.img,
        spec: data.specs,
        price: asRmb(data.price),
        name: data.name,
        _checked: false
      };

shoppingCart数组的每一项都是一个对象,通过商品页面点击添加购物车然后提交到vuex保存,然后取到购物车页面用于渲染。
vue实现购物车页面操作 商品的单选和全选以及商品单价和总价的动态变化_第1张图片

  • 接收选中对象的数组

    goodsCheckList:[ ];
    该数组用于当点击选中某一项商品之后,把商品push进该数组,用于后续的提交表单以及价格计算等。

单选和全选:

iview的Table组件有一个type属性,只要指定 type: ‘selection’,即可自动开启多选功能。

但是有个问题,我需要在购物车页面实现商品数量的增加以及减少,所以每当我进行数量的加减时,必然要去修改数据源shoppingCart里面的对应对象的num属性,然后当我点击按钮操作数量时,左侧的选中状态效果消失了。
在这里插入图片描述
在这里插入图片描述
但是selection里面的项并没有减少,只是选中样式消失了,(selection为Table组件方法的参数,是一个选中项集合的数组),修改数据源shoppingCart就会出现这样的问题,因为数据变化,需要重新渲染。

由于会出现上面的问题,所以没有使用Table组件的多选属性,决定自己来实现,首先是在表的左侧添加checkbox,选择slot属性在模板中插入


 columns: [
        {
          slot: 'picker',
          key: '_checked',
          align: 'center',
          // 自定义表头
          renderHeader: (h, params) => {
            return h('input', {
              domProps: {
                title: '点击全选',
                type: 'checkbox',
                checked: this.allSleStatus
              },
              on: {
                click: () => {
                  this.allSelected();
                }
              }
            });
          }
        },
  • 单选

    单选比较好实现,获取当前项的_checked属性(默认不选中),然后取反,通过判断当前项是否存在于goodsCheckList,来决定是否需要push以及需要修改数据源shoppingCart对应对象的_checked属性true,这样页面上就会自动显示选中效果,取消选中时则将该项从goodsCheckList中删除,和把数据源shoppingCart对应对象的_checked设为false,理由同上,页面自动取消选中效果。

handleSelect (row) {
      let stateChecked = !row._checked;
      if (stateChecked && this.goodsCheckList.indexOf(row) < 0) {
        this.goodsCheckList.push(row);
        this.shoppingCart.map(val => {
          if (val.id === row.id) {
            val._checked = stateChecked;
          }
        });
      } else {
        this.goodsCheckList.splice(this.goodsCheckList.findIndex(val => val.id === row.id), 1);
        this.shoppingCart.map(val => {
          if (val.id === row.id) {
            val._checked = false;
          }
        });
      }
    },
  • 全选

    全选并不是简单的判断当前项的_checked是否为false,如果是则设为true,eles则为false,这是反选。
    全选需要取出数据源每一项的_checked属性,判断是否含有false,如果存在false,则全部置为true,然后通过判断goodsCheckList是否存在来选择push。

allSelected () {
      let statusArr = this.shoppingCart.map(val => val._checked);
      this.shoppingCart.map(val => {
        if (statusArr.indexOf(false) > -1) {
          val._checked = true;
          if (this.goodsCheckList.indexOf(val) < 0) {
            this.goodsCheckList.push(val);
          }
        } else {
          if (val._checked === true) {
            val._checked = false;
            this.goodsCheckList.splice(this.goodsCheckList.findIndex(val => val.id), 1);
          }
        }
      });
    }, // 该方法放在自定义表头来点击执行

全选还有一个要实现的效果,就是当我们手动去选择购物车列表的每一项时,全选按钮要自动勾选上。
vue实现购物车页面操作 商品的单选和全选以及商品单价和总价的动态变化_第2张图片
在计算属性computed中添加一个方法判断数据源shoppingCart每一项的_checked是否都为true,如果全为true则返回true否则返回false

allSleStatus () {
      let stuArr = this.shoppingCart.map(val => val._checked);
      return !(stuArr.indexOf(false) > -1);
    }
商品价格的自动计算
  • 单价

    单价直接就使用Table参数row来通过num和price相乘得出

{
          title: '价格',
          // width: 120,
          align: 'center',
          key: 'price',
          render: (h, params) => {
            let vals = params.row.price * params.row.num;
            return h('span', vals);
          }
        },
  • 总价

    在计算属性computed中添加一个方法,映射goodsCheckList的每一项,通过num和price相乘得到一个数组,再通过数组求和得到总价。

totalPrice: {
      get () {
        if (this.goodsCheckList.length > 0) {
          return this.goodsCheckList.map(val => parseInt(val.price * val.num)).reduce((prev, cur) => prev + cur);
        }
      },
      set (newVal) {
        console.log(newVal, '<-->newVal');
      }
    },

注:数据源shoppingCart也是通过计算属性从vuex中返回来的,所以修改时需要setter

shoppingCart: {
      get () {
        return this.$store.state.cart.shoppingCart;
      },
      set (newVal) {
        console.log(newVal, '<-->newVal');
      }
    },

你可能感兴趣的:(vue,js)