流程
(1):用户一个一个商品的勾选,当摸个店铺下的商品选满则要将该店铺选中,否则不选中该店铺。在所有店铺选满以后,标记选中全选按钮,否则不选中全选按钮。
(2):用户一个店铺一个店铺的勾选,这时要选中标记选中店铺下的所有商品,反之不选中。在所有店铺选满以后,标记选中全选按钮,否则不选中全选按钮。
(3):直接勾选全选按钮,这时要选中所有商品和店铺,反之则不选中。
(4):对以上3中情况做任意组合。
注意点:因为在每次用户点击以后都需要重新计算购物车中的结算价格,此刻则要去和服务端进行交互。
核心思路:采用级联调用,或者说是简单的通知机制
例如:正对体验流程(1)这种情况,可以在勾选商品项的时候做判断,如果该商品项所属的店铺下全部的商品都被勾选了,此刻通知或者说是调用勾选店铺按钮的方法(注:这边强调的是调用方法,而不是单纯的改变店铺按钮的样式)。
对于其他情况,以此类推。
代码思路:
(1) 简单抽象出 用户行为对象(UserAction,和用户做交互的方法集合,一般都为点击事件)、页面行为对象(PageAction,用作更新页面UI的方法集合)、系统行为对象(SystemAction,用户和服务端做交互的方法集合)
(2)由于购物车的复杂性,建议在抽象一个工具对象(CHECKBOX_TOOL),建议实现的方法如下(可以根据具体情况做调整)。
//用于获取checkbox元素的工厂( 由于购物车列表项可能会被移除 每次使用时必须重新获得 )
var CHECKBOX_TOOL = {
all:$(“label[data-selected=’all’]”) ,
/**
* 获取实时的店铺按钮列表 (防止缓存)
* @return {jQuery|HTMLElement}
*/
store: function () {
},
/**
* 获取实时的商品按钮列表 (防止缓存)
* @return {jQuery|HTMLElement}
*/
goods: function () {
},
/**
* 选中状态的css类名称
*/
checkedClzName: ""
};
/**
* 是否被选中
* @param $checkbox 被点击的chexkbox对象
* @param caller 调用者,当调用者不为undeifed的时候,强制放回调用者预期的选中状态
**/
CHECKBOX_TOOL.isSelected = function ($checkbox, caller) {
if (caller != undefined) {
return caller.selected;
}
return TODO;
}
/**
* 设置为选中状态
**/
CHECKBOX_TOOL.setSelected = function ($checkbox) {
}
/**
* 设置为未选中状态
**/
CHECKBOX_TOOL.setUnSelected = function ($checkbox) {
}
/**
* 获取店铺列表
**/
CHECKBOX_TOOL.getStoreList = function () {
return $("label[data-store]");
}
/**
* 获取店铺中的商品项列表
**/
CHECKBOX_TOOL.getStoreGoodsList = function ($checkBox) {
}
/**
* 店铺复选框是否能选中
**/
CHECKBOX_TOOL.storeHasSelected = function ($checkBox) {
}
/**
* 全选按钮是否能够选中
**/
CHECKBOX_TOOL.allButtonHasSelected = function () {
}
(3):
UserAction实现参考(核心思路:使用call或者apply方法改变this对象):
//用户行为对象
var UserAction = {};
/**
* 点击购物车商品项
**/
UserAction.clickGoodsItem = function (event, caller) {
var $self = $(this);
var isSelected = CHECKBOX_TOOL.isSelected($self, caller);
if (isSelected) {
//处于选中状态,置为未选中状态
CHECKBOX_TOOL.setUnSelected($self)
} else {
CHECKBOX_TOOL.setSelected($self)
}
if (caller === undefined || caller === this) {
//是由当前商品项自身发起点击调用,直接调用计算价钱的方法
SystemAction.priceCalculate();
}
//店铺是否能够被选中,并且调用者不是店铺按钮
if (CHECKBOX_TOOL.storeHasSelected($self) && caller === undefined) {
//选中店铺
var $store = $self.parents("dl").find("label[data-store]");
UserAction.clickStoreItem.call($store, null, {isGoods: true, selected: isSelected});
}
}
/**
* 点击购物车店铺项
**/
UserAction.clickStoreItem = function (event, caller) {
var $self = $(this);
var isSelected = CHECKBOX_TOOL.isSelected($self, caller);
if (isSelected) {
//处于选中状态,置为未选中状态
CHECKBOX_TOOL.setUnSelected($self);
} else {
CHECKBOX_TOOL.setSelected($self);
}
//是否能够选中全选按钮 并且调用者不是全选按钮
var allButtonHasSelected = CHECKBOX_TOOL.allButtonHasSelected();
if (allButtonHasSelected ) {
UserAction.clickAllShopCart.call(CHECKBOX_TOOL.all, null, {isStore: true, selected: false});
} else {
UserAction.clickAllShopCart.call(CHECKBOX_TOOL.all, null, {isStore: true, selected: true});
}
//来自商品项按钮的调用 直接return
if (caller !== undefined && caller.isGoods) {
return;
}
//获取店铺下的商品项,调用
CHECKBOX_TOOL.getStoreGoodsList($self).each(function () {
UserAction.clickGoodsItem.call(this, null, {isStore: true, selected: isSelected});
});
//来自当前店铺的点击的调用
//设置店铺为选中状态,并计算价钱
if (caller === undefined || caller === this) {
SystemAction.priceCalculate();
}
}
/**
* 点击全选按钮
**/
UserAction.clickAllShopCart = function (event, caller) {
console.log(caller);
var $self = $(this);
var isSelected = CHECKBOX_TOOL.isSelected($self, caller);
if (isSelected) {
//处于选中状态,置为未选中状态
CHECKBOX_TOOL.setUnSelected($self);
} else {
CHECKBOX_TOOL.setSelected($self);
}
//来自当前全选按钮的点击的调用
//设置店铺为选中状态,并计算价钱
if (caller === undefined || caller === this) {
CHECKBOX_TOOL.getStoreList($self).each(function () {
UserAction.clickStoreItem.call(this, null, {isAll: true, selected: isSelected});
});
SystemAction.priceCalculate();
}
PageAction实现参考:
var PageAction={};
PageAction.updateCartInfo=function(params….){
//TODO 更新购物车信息
}
SystemAction实现参考:
var SystemAction={}
SystemAction.priceCalculate=function(params…){
//这个方法可以由外部传入参数,也可以自行在方法内部获取相关的参数。
//提交Ajax请求,请求成功后调用PageAction.updateCartInfo方法对页面进行更新
}
最终调用代码(移动端可以考虑使用touch时间代替click):
//点击总的全选按钮
CHECKBOX_TOOL.all.click(function (event) {
UserAction.clickAllShopCart.call(this, event);
});
//点击店铺按钮
CHECKBOX_TOOL.store().click(function (event) {
UserAction.clickStoreItem.call(this, event);
});
//点击商品项
CHECKBOX_TOOL.goods().click(function (event,) {
UserAction.clickGoodsItem.call(this, event);
});
js购物车实现的基本思路如上。
注意:在UserAction中要区别出caller是谁,防止循环调用,导致选择状态错误,以及SystemAction.priceCalculate方法多次被调用,导致体验流程不顺畅,以及性能损耗。