一、主要实现的功能
1.商品列表
2.结算功能
3.编辑功能
二、结算功能步骤
1.初始化默认选中项
2.将步进器中选中数量同步
3.引入vant结算功能,实现全选和反选(逻辑有些未搞清楚)
4.计算总价格(注意要*100)
5.结算但是不生成订单(需要vuex,引入结算列表)
三、编辑功能步骤
1.进入编辑页面后的删除功能,判断是否有数据,
2.利用全局总线的方式发布消息,是否可以进入到编辑状态,如果购物车列表数组不为空,则可以进入到编辑页面(myCart、header组件)
3.修改页面,定义一个isDelete,v-if判断如果为false,则为删除,接收全局总线消息(cartDetails组件)
4.更新数据,传入type,删除之后更新购物车数组,结算功能中传入2(type==1为删除,type==2为更新)
5.来回切换(编辑和完成组件之间)
6. 修改isShow,编辑功能中将购物车所有列表删除完毕之后,显示空组件,头部变成编辑两个字
四、完整代码
下载 npm i mitt -S
common->js->eventbus.js
import mitt from "mitt"
const emitter=mitt()
export default emitter
components->Header.vue
<template>
<div class="header">
<van-icon name="arrow-left" class="icon" />
<div>{{ title }}</div>
<div class="edit" v-if="edit" @click="editClick">
{{ store.state.edit ? "编辑" : "完成" }}
</div>
</div>
</template>
<script>
import { defineComponent } from "vue";
import { useStore } from "vuex";
import emitter from "../common/js/evenbus";
import { Toast } from "vant";
export default defineComponent({
name: "App",
props: ["title", "edit"],
setup() {
const store = useStore();
const editClick = () => {
// 判断如果购物车列表不为空,则发布全局事件总线消息,意味着可以进入编辑
if (store.state.cartList.length) {
console.log("进入编辑页面");
store.commit("EDIT");
emitter.emit("edit");
} else {
Toast.fail("购物车空空如也");
}
};
return {
editClick,
store,
};
},
});
</script>
<style lang="less" scoped>
.header {
background-color: #fff;
height: 40px;
font-size: 20px;
display: flex;
justify-content: center;
align-items: center;
border-bottom: 1px solid #d7d7d7;
.icon {
position: absolute;
left: 10px;
}
.edit {
position: absolute;
right: 15px;
font-size: 18px;
}
}
</style>
pages->myCart->MyCart.vue
<template>
<div class="cart">
<Header title="购物车" :edit="true" />
<Cart-details v-if="isShow" :changeShow="changeShow" />
<Blank v-else />
<Footer />
</div>
</template>
<script>
import { defineComponent, ref } from "vue";
import Blank from "../../components/Blank.vue";
import Footer from "../../components/Footer.vue";
import Header from "../../components/Header.vue";
import CartDetails from "./component/CartDetails.vue";
import { useStore } from "vuex";
export default defineComponent({
name: "App",
components: { Footer, Header, Blank, CartDetails },
setup() {
const isShow = ref(false);
const store = useStore();
const init = () => {
if (store.state.cartList.length) {
isShow.value = true;
}
};
init();
// 编辑功能中:通知展示商品列表还是空组件
const changeShow = () => {
isShow.value = !isShow.value;
};
return {
isShow,
changeShow,
};
},
});
</script>
<style lang="less" scoped>
.cart {
display: flex;
flex-flow: column;
height: 100%;
.content {
flex: 1;
overflow-y: auto;
}
}
</style>
pages->myCart->component->CartDetails.vue
<template>
<div class="cartDetails">
<div class="content">
<van-checkbox-group
v-model="result"
ref="checkboxGroup"
@change="groupChange"
>
<div v-for="(i, index) in store.state.cartList" :key="index">
<FoodAdd :item="i" :showCheckbox="true" :onChange="onChange" />
</div>
</van-checkbox-group>
</div>
<!-- 结算 -->
<van-submit-bar
:price="allPrice * 100"
button-text="结算"
@submit="onSubmit"
button-color="#ffc400"
v-if="isDelete"
>
<van-checkbox v-model="checked" checked-color="#ffc400" @click="checkAll"
>全选</van-checkbox
>
</van-submit-bar>
<!-- 删除 -->
<van-submit-bar
:price="allPrice * 100"
button-text="删除"
button-color="#ffc400"
@submit="deleteClick"
v-else
>
<van-checkbox
v-model="checked"
checked-color="#ffc400"
@click="checkAll"
class="edit"
>全选</van-checkbox
>
</van-submit-bar>
<!-- <Footer /> -->
</div>
</template>
<script>
import { defineComponent, reactive, toRefs, onMounted, computed } from "vue";
import Footer from "../../../components/Footer.vue";
import FoodAdd from "../../../components/FoodAdd.vue";
import { useStore } from "vuex";
import { Toast } from "vant";
import emitter from "../../../common/js/evenbus";
export default defineComponent({
name: "App",
components: { FoodAdd, Footer },
props: ["changeShow"],
setup(props) {
const store = useStore();
let data = reactive({
result: [],
checked: false,
isDelete: true, //编辑功能中: 是否删除,如果true,显示结算;false,显示删除
});
// 1.初始化选中项数组,
const init = () => {
data.result = store.state.cartList.map((item) => item.id);
};
// 2.将步进器中选中数量同步
const onChange = (value, detail) => {
console.log("结算功能value", value);
console.log("结算功能detail", detail);
store.state.cartList.map((item) => {
if (item.id == detail.name) {
item.num = value;
}
});
};
// 3.全选
const checkAll = () => {
if (data.result.length == store.state.cartList.length) {
// console.log("data.result.length", data.result.length);
// console.log("store.state.cartList.length", store.state.cartList.length);
data.result = [];
// init();
} else {
// data.result = [];
// console.log("data.result.length", data.result.length);
// console.log("store.state.cartList.length", store.state.cartList.length);
init();
}
};
// 3.反选
const groupChange = () => {
if (data.result.length == store.state.cartList.length) {
data.checked = true;
} else {
data.checked = false;
}
};
// 4.计算总价格
const allPrice = computed(() => {
let constList = store.state.cartList.filter((item) =>
data.result.includes(item.id)
);
let sum = 0;
constList.forEach((item) => {
return (sum += item.num * item.price);
});
return sum;
});
onMounted(() => {
init();
});
// 更新数据,type: 1.删除 2.更新
const update = (type) => {
return store.state.cartList.filter((item) => {
return type == 2
? data.result.includes(item.id)
: !data.result.includes(item.id);
});
};
// 5.结算
const onSubmit = () => {
if (data.result.length != 0) {
console.log("结算完成,但不跳转链接");
store.commit("PAY", update(2));
} else {
Toast.fail("请选择商品");
}
};
// const addClick = () => {};
// 编辑功能中:删除
const deleteClick = () => {
// 如果有商品
if (data.result.length) {
// 更新vuex中的cartList, update方法中的type值(1.删除,2.更新)
store.commit("DELETE", update(1));
// 删除后的选中项
data.result = [];
if (store.state.cartList.length == 0) {
// 通知vuex中EDIT方法,进行切换
store.commit("EDIT", "delete");
// 调用父组件中切换 isShow 的方法
props.changeShow();
}
} else {
Toast.fail("请选择要删除的商品!");
}
};
// 接收全局总线消息,监听全局总线中的编辑是否触发
emitter.on("edit", () => {
data.isDelete = !data.isDelete;
});
return {
...toRefs(data),
store,
// addClick,
onChange,
onSubmit,
checkAll,
groupChange,
allPrice,
deleteClick,
};
},
});
</script>
<style lang="less" scoped>
.cartDetails {
font-size: 14px;
flex: 1;
position: relative;
overflow-y: auto;
padding: 20px 20px 55px;
.content {
background-color: white;
border-radius: 10px;
padding: 10px;
}
.van-submit-bar {
position: fixed;
bottom: 52px;
}
.edit {
position: fixed;
left: 15px;
font-size: 16px;
}
}
</style>
五、上传git
六、小问题
1.在进入编辑界面后,点击全选按钮,会将所有数据进行删除;但是勾选某一个或几个商品,点击删除按钮,并为出现任何问题,会将对应的数据进行删除。