vue实现购物车页面操作 商品的单选和全选以及商品单价和总价的动态变化
vue框架搭建,UI库使用的是iview,购物车页面使用iview的table组件,没有用到element,不知道实现起来效果怎么样,感觉iview有点坑。准备工作:数据源shoppingCart:[ ];该数据数据结构如下const items = {id: data.id,num: data.num,img: data.img...
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保存,然后取到购物车页面用于渲染。
-
接收选中对象的数组
goodsCheckList:[ ];
该数组用于当点击选中某一项商品之后,把商品push进该数组,用于后续的提交表单以及价格计算等。
单选和全选:
iview的Table组件有一个type属性,只要指定 type: ‘selection’,即可自动开启多选功能。
但是有个问题,我需要在购物车页面实现商品数量的增加以及减少,所以每当我进行数量的加减时,必然要去修改数据源shoppingCart里面的对应对象的num属性,然后当我点击按钮操作数量时,左侧的选中状态效果消失了。
但是selection里面的项并没有减少,只是选中样式消失了,(selection为Table组件方法的参数,是一个选中项集合的数组),修改数据源shoppingCart就会出现这样的问题,因为数据变化,需要重新渲染。
由于会出现上面的问题,所以没有使用Table组件的多选属性,决定自己来实现,首先是在表的左侧添加checkbox,选择slot属性在模板中插入
<template slot-scope="{ row }"
slot="picker">
<span @click="handleSelect(row)">
<Checkbox v-model="row._checked"></Checkbox>
</span>
</template>
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);
}
}
});
}, // 该方法放在自定义表头来点击执行
全选还有一个要实现的效果,就是当我们手动去选择购物车列表的每一项时,全选按钮要自动勾选上。
在计算属性computed中添加一个方法判断数据源shoppingCart每一项的_checked是否都为true,如果全为true则返回true否则返回false
allSleStatus () {
let stuArr = this.shoppingCart.map(val => val._checked);
return !(stuArr.indexOf(false) > -1);
}
商品价格的自动计算
{
title: '价格',
// width: 120,
align: 'center',
key: 'price',
render: (h, params) => {
let vals = params.row.price * params.row.num;
return h('span', vals);
}
},
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');
}
},
更多推荐
所有评论(0)