效果实现(续):
(1)规格商品
规格商品,点击后出现:
{{choosedFoods.specifications[0].name}}
-
{{item}}
说明:
showSpecs:控制显示上商品规格的弹出层,初始弹出层不显示,showSpecs值为false
showChooseList:点击时通过改变showSpecs的值,来改变规格弹出层的显示和隐藏
choosedFoods和foods的值相同,其数据结构如下:
chooseSpecs:该方法用于记录当前所选规格的索引值
选择规格商品之后:
多规格商品只能去购物车删除哦
说明:
showDeleteTip:多规格商品点击减按钮。弹出提示框。showDeleteTip的初始值为false
(2)下落小球
函数部分:
##### 说明
(1)加减按钮:
listenInCart:监听圆点是否进入购物车
showChooseList:是否显示规格列表
showReduceTip:是否显示"无法减去规格"商品的提示语
showMoveDotFun:显示下落小球
(2)totalNum:购物车中总共的商品数量
shopDetailData:商铺详情数据
通过
this.shopDetailData = await shopDetails(
this.shopId,
this.latitude,
this.longitude
);
方法拿到,其数据结构如下:
来源于initCategoryNum方法。该方法的作用在于在初始化、点击+/-商品时。获取加入购物车中的商品数量。
(细节部分不是很明白[○・`Д´・ ○]理解还是不是很深入)
export default{
data(){
//geohash位置信息
geohash: "",
//购物车商品列表
cartFoodList:[],
//商铺详情数据
shopDetailData:null,
//总价格
totalPrice:0,
//商店id值
shopId: null,
//当前选中的食品数据
choosedFoods: null,
//控制显示食品规格
showSpecs:false,
//当前选中的规格索引值
specsIndex: 0,
//多规格商品点击减按钮。弹出提示框,初始值为false,也就是默认不弹出
showDeleteTip:false,
//显示购物车商品列表(初始值为false,不显示,有加入购物车的商品时,点击购物车图标,来控制其显示还是隐藏)
showCartList:false,
//已加入购物车的商品列表
cartFoodList: [],
//控制下落的小圆点的显示隐藏
showMoveDot: [],
//购物车下落圆球是否抵达指定位置
receiveInCart:false,
//商品右上角已加入购物车的数量
categoryNum:[],
//食品列表,初始值为[]
menuList:[]
},
computed:{
...mapState(["latitude", "longitude", "cartList"]),
//购物车中商品总数量
totalNum:function(){
//初始状态下cartFoodList的值为[],totalNum的值为0
let num=0;
this.cartFoodList.forEach(item=>{
num+=item.num;
});
return num;
},
//minimumOrderAmount还差多少元起送
minimumOrderAmount:function(){
//拿到了shopDetailData之后执行
if(this.shopDetailData){
//还差多少元起送=最低起送价-总价
return this.shopDetailData.float_minimum_order_amount - this.totalPrice;
}
else{
return null;
}
},
//当前商铺购物信息
shopCart:function(){
return {...this.cartList[this.shopId]}
}
},
created(){
//坐标
this.geohash=this.$route.query.geohash;
//商铺id
this.shopId=this.$route.query.id;
this.INIT_BUYCART();
},
methods:{
...mapMutations([
//加入购物车的方法
'ADD_CART',
//移出购物车的方法
'REDUCE_CART',
//初始化购物车
'INIT_BUYCART',
//清空购物车
'CLEAR_CART',
]),
...
//点击"选规格"的时候执行-显示规格列表
showChooseList(foods){
if(foods){
//choosedFoods已选中的食品数据就等于当前点击项,所在item的list
this.choosedFoods=foods;
},
//规格弹出层的"显示"/"隐藏"切换
this.showSpecs=!this.showSpecs;
//当前选中的规格索引值
//重置当前所选中规格的索引值
this.specsIndex=0;
},
//控制显示无法减去规格商品的提示语
showReduceTip(){
this.showDeleteTip=true;
clearTimeout(this.timer);
this.timer=setTimeout(()=>{
//3秒之后清空定制器
clearTimeout(this.timer);
//将提示语进行隐藏
this.showDeleteTip=false;
},3000);
},
//记录当前所选规格的索引值,(目的)在于给当前所选项添加active状态的class
chooseSpecs(index){
this.specsIndex=index;
},
/*加入购物车:传入参数
category_id-食品分类id
item_id-食品id
food_id-食品规格id
name-食品名字
price-食品价格
specs-食品规格
*/
addToCart(category_id, item_id, food_id, name, price, specs){
//this.ADD_CART方法在mutations.js中定义
this.ADD_CART({
//店铺id
shopid:this.shopId,
//食品分类id
category_id,
//食品id
item_id,
//食品规格id
food_id,
//食品名字
name,
//食品价格
price,
//食品规格
specs
});
},
//移出购物车:
removeOutCart(category_id, item_id, food_id, name, price, specs){
this.REDUCE_CART({
//店铺id
shopid:this.shopId,
//食品分类id
category_id,
//食品id
item_id,
//食品规格id
food_id,
//食品名字
name,
//食品价格
price,
//食品规格
specs
});
},
//多规格商品加入购物车
/*传入参数
category_id-食品分类id
item_id-食品id
food_id-食品规格id
name-食品名字
price-食品价格
specs-食品规格
packing_fee:打包费
sku_id:库存id
stock:库存
*/
addSpecs(category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock){
this.ADD_CART({shopid:this.shopId,
category_id,
item_id,
food_id,
name,
price,
specs,
packing_fee,
sku_id,
stock
});
//规格商品加入购物车之后,隐藏规格的弹出层
this.showChooseList();
},
//清空购物车
clearCart(){
//点击了
this.CLEAR_CART(this.shopId);
//隐藏已展示的购物车列表
this.toggleCartList();
},
//控制已加入购物车的商品列表的显示和隐藏
toggleCartList(){
//cartFoodList已加入购物车的商品列表,初始值为[]
//showCartList的值控制是否显示列表
this.cartFoodList.length ? this.showCartList=!this.showCartList:true
},
//显示下落小球
showMoveDotFun(showMoveDot, elLeft, elBottom){
//点击加号之后,this.showMoveDot的值从[],变成true,下落的小圆球显示
this.showMoveDot=[...showMoveDot,...showMoveDot];
//应该是初始状态小球的位置吧
this.elLeft=elLeft;
this.elBottom=elBottom;
},
//动画初次渲染前
beforeEnter(el){
//初次渲染的时候,确定小球的位置
// 设置transform值
el.style.transform = `translate3d(0,${37 + this.elBottom - this.windowHeight}px,0)`;
el.children[0].style.transform = `translate3d(${this.elLeft - 30}px,0,0)`;
//设置不透明度
el.children[0].style.opacity = 0;
},
//动画渲染后(让小球从当前位置移动到底部)
afterEnter(el){
el.style.transform=`translate3d(0,0,0)`;
el.children[0].style.transform=`translate3d(0,0,0)`;
el.style.transition = 'transform .55s cubic-bezier(0.3, -0.25, 0.7, -0.15)';
el.children[0].style.transition = 'transform .55s linear';
//到达底部之后把下落的小球隐藏起来
this.showMoveDot = this.showMoveDot.map(item => false);
//设置不透明度
el.children[0].style.opacity = 1;
//判断是否已经到达底部
el.children[0].addEventListener('transitionend',()=>{
this.listenInCart();
});
el.children[0].addEventListener('webkitAnimationEnd',()=>{
this.listenInCart();
});
},
//监听小圆球是否进入购物车
listenInCart(){
//receiveInCart的初始值为false,用来判断下落的小圆球是否抵达指定位置
if(!receiveInCar){
this.receiveInCart=true;
this.$refs.cartContainer.addEventListener('animationend',()=>{
this.receiveInCart=false;
});
this.$refs.cartContainer.addEventListener('webkitAnimationEnd',()=>{
this.receiveInCart = false;
});
}
},
/*初始化和shopCart变化时,重新湖区购物车改变过的数据,
赋值 categoryNum,totalPrice,cartFoodList,整个数据流是自上而下的形式,
商品右上角已加入购物车的数量categoryNum[]
totalPrice:总价格,初始值是0
cartFoodList:已加入购物车的商品列表初始值是[]
*/
initCategoryNum(){
//一个空数组
let newArr=[];
//初始状态下,已加入购物车的商品数量
let cartFoodNum=0;
//已加入购物车的商品总价,初始值为0
this.totalPrice=0;
//已加入购物车的商品列表
this.cartFoodList=[];
this.menuList.forEach((item,index)=>{
if(this.shopCart&&this.shopCart[item.foods[0].category_id]){
let num=0;
Object.keys(this.shopCart[item.foods[0].category_id]).forEach(itemid=>{
Object.keys(this.shopCart[item.foods[0].category_id][itemid]).forEach(foodid=>{
let foodItem = this.shopCart[item.foods[0].category_id][itemid][foodid];
num+=foodItem.num;
//item.type==1可以说明什么吗?
if(item.type==1){
this.totalPrice+=foodItem.num*foodItem.price;
if(foodItem.num>0){
this.cartFoodList[cartFoodNum] = {};
this.cartFoodList[cartFoodNum].category_id = item.foods[0].category_id;
this.cartFoodList[cartFoodNum].item_id = itemid;
this.cartFoodList[cartFoodNum].food_id = foodid;
this.cartFoodList[cartFoodNum].num = foodItem.num;
this.cartFoodList[cartFoodNum].price = foodItem.price;
this.cartFoodList[cartFoodNum].name = foodItem.name;
this.cartFoodList[cartFoodNum].specs = foodItem.specs;
cartFoodNum ++;
}
}
});
})
//已加入购物车的商品数量
newArr[index] = num;
}
else{
newArr[index] = 0;
}
this.totalPrice = this.totalPrice.toFixed(2);
this.categoryNum = [...newArr];
})
},
...
},
watch:{
//showLoading变化时说明组件已经获取初始化数据,在下一帧nextTick进行后续操作
showLoading:function(value){
if(!value){
this.$nextTick(()=>{
//获取食品列表的高度
this.getFoodListHeight();
//初始化和shopCart变化时,重新获取购物车改变过的数据
this.initCategoryNum();
});
}
},
//当前商店购物信息
shopCart:function(value){
this.initCategoryNum();
},
//购物车列表发生变化,没有商铺时隐藏
//cartFoodList:购物车商品列表
cartFoodList:function(value){
if(!value.length){
this.showCartList = false;
}
}
}
}
mutations.js中定义的方法:
//引入常量
import {
SAVE_GEOHASH,
RECORD_ADDRESS,
ADD_CART,
REDUCE_CART,
CLEAR_CART,
BUY_CART,
SAVE_SHOPID,
INIT_BUYCART,
RECORD_SHOPDETAIL
} from './mutation-types.js'
import { setStore, getStore } from '../config/mUtils';
export default {
//保存geohash
[SAVE_GEOHASH](state, geohash) {
state.geohash = geohash;
},
//记录当前具体的位置信息
[RECORD_ADDRESS](state, {
latitude,
longitude
}) {
state.latitude = latitude;
state.longitude = longitude;
},
//加入购物车
[ADD_CART](state, {
shopid,
category_id,
item_id,
food_id,
name,
price,
specs,
packing_fee,
sku_id,
stock
}) {
let cart = state.cartList;
let shop = cart[shopid] = (cart[shopid] || {});
let category = shop[category_id] = (shop[category_id] || {});
let item = category[item_id] = (category[item_id] || {});
if (item[food_id]) {
item[food_id]['num']++;
} else {
item[food_id] = {
"num" : 1,
"id" : food_id,
"name" : name,
"price" : price,
"specs" : specs,
"packing_fee" : packing_fee,
"sku_id" : sku_id,
"stock" : stock
};
}
state.cartList = {...cart};
//存入localStorage
setStore('buyCart', state.cartList);
},
//移出购物车
[REDUCE_CART](state, {
shopid,
category_id,
item_id,
food_id,
name,
price,
specs,
}) {
let cart = state.cartList;
let shop = (cart[shopid] || {});
let category = (shop[category_id] || {});
let item = (category[item_id] || {});
if (item && item[food_id]) {
if (item[food_id]['num'] > 0) {
item[food_id]['num']--;
state.cartList = {...cart};
//存入localStorage
setStore('buyCart', state.cartList);
} else {
//商品数量为0,则清空当前商品的信息
item[food_id] = null;
}
}
},
//清空当前商品的购物车信息
[CLEAR_CART](state,shopid){
state.cartList[shopid] = null;
state.cartList = {...state.cartList};
setStore('buyCart', state.cartList);
},
//保存商铺id
[SAVE_SHOPID](state, shopid) {
state.shopid = shopid;
},
//初始化购物车
[INIT_BUYCART](state){
let initCart=getStore('buyCart');
if(initCart){
state.cartList=JSON.parse(initCart);
}
},
//RECORD_SHOPDETAIL
[RECORD_SHOPDETAIL](state,detail){
state.shopDetail=detail;
}
}
参照项目地址:地址