cart购物车

在这里插入图片描述
在这里插入图片描述
组件数据(部分):

selectFood是个对象 里面存储的selectFood.餐馆id.食物id = true/false 表示该餐馆中的该食物是否被选中
selectFood.餐馆id.totalPrice 表示该餐馆中食物的总价格
selectFood.餐馆id.allSelect = true/false 表示该餐馆中的所有食物是否被全部选中

deleteSelectFood是个对象 里面存储的deleteSelectFood.餐馆id.食物id = true/false 表示该餐馆中的该食物是否被选中删除
deleteSelectFood.餐馆id.allSelect = true/false 表示该餐馆中的所有食物是否被全部选中删除

组件一创建 查看vuex中的cartList是否有数据(是否为空) 为空代表购物车里面没有东西 并将结果保存在emptyCart变量中

created() {
	this.emptyCart = !Object.keys(this.cartList).length
    /*cartList是个对象 对象里面的键是restaurant_id 值也是个对象 restaurant_id中保存的是该商店中加入购物车的食品*/
    Object.keys(this.cartList).forEach(restaurant_id => {
    	// 初始化数据
    	this.selectFood[restaurant_id] = {// 初始化选中列表
          	allSelect: true,
          	totalPrice: 0
        };
        this.deleteSelectFood[restaurant_id] = {// 初始化删除列表
          	allSelect: false
        }
        let restaurant = this.cartList[restaurant_id];
        Object.keys(restaurant).forEach(data => {
          	if (Number(data)) {
            	this.deleteSelectFood[restaurant_id][data] = false;
            	this.selectFood[restaurant_id][data] = true;
            	this.selectFood[restaurant_id]['totalPrice'] += Number(restaurant[data]['price']) * Number(restaurant[data]['num']);
          	}
        })
	});
}

顶部导航条:复用head组件

在这里插入图片描述
在这里插入图片描述
复用head组件 右上角插槽展示编辑/取消 通过editStatus变量控制展示哪一个 点击后通过改变editStatus变量来切换展示

<v-head title="购物车" goBack="true" bgColor="#f4f4f4">
	<!--editStatus为false 展示这个组件-->
	<span slot="edit-cart" class="edit" @click="editStatus = true;" v-if="!editStatus">编辑</span>
	<!--editStatus为true 展示这个组件-->
	<span slot="cancel-edit-cart" class="edit" @click="editStatus = false;" v-else>取消</span>
</v-head>

购物车为空

在这里插入图片描述
如果emptyCart为true 代表购物车为空 展示一个图片 一行字 一个router-link包裹的文字 点击后跳转到首页

<div class="empty-cart" v-if="emptyCart">
	<div class="info-container">
    	<img src="../../assets/nothing.png">
        <span class="text">购物车空空如也,快去逛逛吧</span>
        <router-link class="redirect-index" to="/index"><span>去逛逛</span></router-link>
    </div>
</div>

商店

在这里插入图片描述

  1. 在非编辑状态下(editStatus为false)也就是我们一进入购物车组件时 所有商品被选中(selectFood[restaurant_id]['allSelect'] = true) 展示√这个iconfont 并将所有商品加入allSelect
    在这里插入图片描述
<span
	class="selected"
    v-if="!editStatus && selectFood[restaurant_id]['allSelect'] === true"
    @click="allSelect(restaurant_id,false)">
	<i class="iconfont">&#xe6da;</i>
</span>
<span
	class="select"
    v-else-if="!editStatus"
    @click="allSelect(restaurant_id,true)">
</span>
<!--展示餐馆的照片 item是从cartList中遍历出来的商店信息-->
<span class="restaurant-picture">
	<img :src="item.pic_url">
</span>
<!--展示餐馆的名称-->
<span class="restaurant-name">{{item.restaurant_name}}</span>
  1. 在编辑状态下(editStatus为true) 展示“取消”及下面页面 此时这个小圆圈是一个空白小圆圈
    在这里插入图片描述
    点击它后会全部选中该商店下所有商品 此时将这些商品在deleteSelectFood中的标志位全设为true 将deleteSelectFood中的全部选中删除标志位allSelect设为true 展示√这个iconfont
    在这里插入图片描述
<!--
	editStatus为true(在编辑状态下) 并且如果全部选中删除标志位为true 表示该商店下所有商品都被选中 
	此时商店旁边的那个圈需要选中 只有在这种情况下 商店旁边的那个圈才需要选中
-->
<span
	class="delete-selected selected"
    v-if="editStatus && deleteSelectFood[restaurant_id]['allSelect'] === true"
    @click="allSelectDelete(restaurant_id,false)">
    	<i class="iconfont">&#xe6da;</i>
</span>
<!--editStatus为true 在编辑状态下 就展示个空白的圈-->
<span
	class="select"
	v-else-if="editStatus"
    @click="allSelectDelete(restaurant_id,true)">
</span>
<script>
allSelectDelete(restaurant_id, boolean) {   //删除状态下的全选
	this.deleteSelectFood[restaurant_id]['allSelect'] = boolean;// 设置全选删除标识符
    //将deleteSelectFood中该商店的所有食物都变为true 表示他们选中删除
    Object.keys(this.deleteSelectFood[restaurant_id]).forEach(el => {
    	if (Number(el))
            this.deleteSelectFood[restaurant_id][el] = boolean;
        })
    this.deleteSelectFood = {...this.deleteSelectFood};   //拓展运算符使vue更新视图
},
</script>

删除组件

在这里插入图片描述
在编辑状态下(editStatus为true) 展示底部删除

<footer class="btn-delete" v-show="editStatus" @click="deleteCart()">
	<span>删除</span>
</footer>

点击底部删除后遍历deleteSelectFood中的restaurant_id 根据restaurant_id遍历food_id 若deleteSelectFood.餐馆id.食物id = true表示该餐馆中的该食物被选中 要删除 调用vuex中的deleteFood方法 删除vuex中购物车中该餐馆的食品 删除selectFood、deleteSelectFood中该餐馆的指定食品 删除之后展示下面的页面 页面所有商品全部不选中 所以调用allSelect重置
在这里插入图片描述
deleteSelectFood.餐馆id.食物id = true/false 表示该餐馆中的该食物是否被选中删除
deleteSelectFood.餐馆id.allSelect = true/false 表示该餐馆中的所有食物是否被全部选中删除

deleteCart() {//删除购物车 从vuex中的购物车删除deleteSelectFood中的内容
	Object.keys(this.deleteSelectFood).forEach((restaurant_id) => {
    	let restaurant = this.deleteSelectFood[restaurant_id];  //商店
        Object.keys(restaurant).forEach(food_id => {    //要删除的商品
        	if (Number(food_id) && restaurant[food_id]) {
            	this.$store.dispatch('deleteFood', {restaurant_id, food_id})//删除购物车数据
              	delete this.selectFood[restaurant_id][food_id];// 删除selectFood中该餐馆的指定食品
            }
            this.allSelect(restaurant_id, false);//重置选中列表为false 因为删除商品后 页面所有商品全部不选中
            delete restaurant[food_id];// 删除deleteSelectFood中该餐馆中指定食品
		})
	})
    this.editStatus = false;// 从编辑状态变为正常状态
    this.emptyCart = !Object.keys(this.cartList).length;// 删除完商品后判断一下购物车是否为空
}

//删除食物
[types.DELETE_FOOD](state, {restaurant_id, food_id}) {
	let cart = state.cartList;// 购物车
    let restaurant = cart[restaurant_id];// 餐馆
    let num = restaurant[food_id].num;// 餐馆中的该食品总数
    let price = restaurant[food_id].price;// 餐馆中该食品的价格
    restaurant.totalNum -= num;// 餐馆总食品数量 - 餐馆中该食品的总数
    delete(restaurant[food_id]);// 删除参观中该食品
    if (restaurant.totalNum === 0) {// 如果餐馆中食品数量为0 从购物车中删除该餐馆
    	delete(cart[restaurant_id]);
    } else {//否则修改餐馆的总价格 = 餐馆的总价格 - 食品数量 * 食品总数
    	restaurant.totalPrice = Number((restaurant.totalPrice - price * num).toFixed(2)); 
    }
    state.cartList = {...cart};// 更改vuex中的购物车内容
    localStorage.setItem('cartList', JSON.stringify(state.cartList));// 将购物车中的内容保存在localStorage中
}

allSelect(restaurant_id, boolean) {//设置某个餐馆的食品是全选还是不全选
	this.selectFood[restaurant_id]['allSelect'] = boolean;//先设置该餐馆的全选标志
    Object.keys(this.selectFood[restaurant_id]).forEach(el => {
    //遍历该餐馆下的所有食品 为每个食品设置全选/全不选
    	if (Number(el)) this.selectFood[restaurant_id][el] = boolean;
    })

	if (boolean) {//如果是选中 计算价格 遍历餐馆中的所有食物 计算总价 = 商品数量 * 价格
    	let restaurant = this.cartList[restaurant_id];
        Object.keys(restaurant).forEach(el => {
            if (Number(el)) {
              	this.selectFood[restaurant_id]['totalPrice'] += restaurant[el]['num'] * restaurant[el]['price'];
            }
        });
	} else {//取消全选 selectFood中该餐馆的totalPrice为0
    	this.selectFood[restaurant_id]['totalPrice'] = 0;
    }
    this.selectFood = {...this.selectFood};   //拓展运算符使vue更新视图
}

商品

遍历前面遍历出来的商店信息里面的商品信息

  1. editStatus为true(在编辑状态下)并且如果该商品被选中 该商品前面的小圆圈展示√这个iconfont 点击这个小圆圈后 该商品取消删除 如果该商品未被选中 点击后 选中该商品
<span class="selected delete-selected"
	v-if="editStatus && deleteSelectFood[restaurant_id][foodKey] === true"
    @click="cancelSelectDelete(restaurant_id,foodKey)">
    <i class="iconfont">&#xe6da;</i>
</span>
<span class="select delete-select"
	v-else-if="editStatus"
    @click="selectDelete(restaurant_id,foodKey)">
</span>
<script>
	cancelSelectDelete(restaurant_id, foodKey) {//取消删除选中
        this.deleteSelectFood[restaurant_id][foodKey] = false;//该商品删除选中为false
        this.deleteSelectFood[restaurant_id]['allSelect'] = false;//全选标志为false
        this.deleteSelectFood = {...this.deleteSelectFood};//拓展运算符使vue更新视图
      }
      selectDelete(restaurant_id, foodKey) {  //选中删除商品
        this.deleteSelectFood[restaurant_id][foodKey] = true; //该商品选中置为true
        //判读是否全选
        let newObj = {...this.deleteSelectFood[restaurant_id]};
        let allSelect = this.isAllSelect(newObj, restaurant_id);
        this.deleteSelectFood[restaurant_id]['allSelect'] = allSelect;
        this.deleteSelectFood = {...this.deleteSelectFood};   //拓展运算符使vue更新视图
      }
      isAllSelect(newObj) {//判断商品是否全选中了 如果全选中那么商家头像左边的按钮对应选中
        delete newObj.allSelect;
        let values = Object.values(newObj);
        let noAllSelect = values.some((el) => {
          if (el === false)
            return true;
        });
        return !noAllSelect;
      }
</script>
  1. editStatus为false(在非编辑状态下)并且如果该商品被选中 该商品前面的小圆圈展示√这个iconfont 点击这个小圆圈后 该商品取消删除 如果该商品未被选中 点击后 选中该商品
<span
	class="selected"
    v-if="!editStatus && selectFood[restaurant_id][foodKey] === true"
    @click="cancelSelect(restaurant_id,foodKey)">
    <i class="iconfont">&#xe6da;</i>
</span>
<span
	class="select"
    v-else-if="!editStatus"
    @click="select(restaurant_id,foodKey)">
</span>
<script>
	cancelSelect(restaurant_id, foodKey) {    //取消选中商品
        this.selectFood[restaurant_id][foodKey] = false;    //该商品取消选中
        this.selectFood[restaurant_id]['allSelect'] = false;    //全选标志为false
        let cartFoodData = this.cartList[restaurant_id][foodKey];  //购物车中 该商品信息
        this.selectFood[restaurant_id]['totalPrice'] -= cartFoodData['num'] * cartFoodData['price'];  //修改价格
        this.selectFood = {...this.selectFood};   //拓展运算符使vue更新视图
      }
	select(restaurant_id, foodKey) {      //选中商品
        this.selectFood[restaurant_id][foodKey] = true;   //该商品选中置true
        let cartFoodData = this.cartList[restaurant_id][foodKey];  //购物车中 该商品信息
        this.selectFood[restaurant_id]['totalPrice'] += cartFoodData['num'] * cartFoodData['price'];  //修改价格
        //判读是否全选
        let newObj = {...this.selectFood[restaurant_id]};
        let allSelect = this.isAllSelect(newObj, restaurant_id);
        this.selectFood[restaurant_id]['allSelect'] = allSelect;
        this.selectFood = {...this.selectFood};   //拓展运算符使vue更新视图
      }
</script>

展示食品图片、名称、数量、价格

<div class="picture-container">
	<img :src="food.foods_pic">
</div>
<div class="info">
	<span class="name">{{food.name}}</span>
<div>
<span class="num">x{{food.num}}</span>
<span class="price">¥{{food.price}}</span>

在这里插入图片描述
editStatus为false(在非编辑状态下)展示“去结算” 点击后执行submit方法 进行提交前的判断 有无商品呈现的“去结算”不一样 动态为其绑定样式

<div class="bottom" v-show="!editStatus">
	<span class="submit"
    	@click="submit(restaurant_id)"
        :class="{active:!selectFood[restaurant_id]['totalPrice']}">去结算
	</span>
	<!--取出总价展示-->
    <span class="total-price">¥{{selectFood[restaurant_id]['totalPrice'].toFixed(2)}}</span>
</div>
<script>
	submit(restaurant_id) { //提交订单
        if (!this.selectFood[restaurant_id].totalPrice) return;//如果没有选中食物 不能提交订单
        let restaurant = this.selectFood[restaurant_id];//选中食物的餐馆
        let foods = {
          totalPrice: 0,
          totalNum: 0
        };
        Object.keys(restaurant).forEach(el => {//计算价格 遍历餐馆中的食物
          if (Number(el) && restaurant[el]) {
            let food = this.cartList[restaurant_id][el];
            foods[el] = food;// 把食品保存在foods中
            foods['totalPrice'] += food.num * food.price;// 计算价格
            foods['totalNum'] += food.num;// 计算商品数量
          }
        })
        let data = {
          restaurant_id,
          foods
        };
        localStorage.setItem('confirmOrderData', JSON.stringify(data));// 将商品保存在localStorage中
        this.$router.push({path: '/confirm_order'});// 跳转到订单确认页面
      }
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值