效果圖:
web端
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLjFGM2YWMjVDO1QmY1UjNiJjZ4QzYlFGM4YDZiJTMhhzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
手機端
iphon5 小屏手機上效果如下:
代碼:
<template>
<div>
<div class="cart-header">
<div class="cart-header-contain">
<div class="cart-title">購物車</div>
</div>
</div>
<!-- 網頁端樣式 -->
<div v-if="!isMobile" class="cart-web">
<!-- 導航欄
左邊logo 右邊搜尋
内容 單欄購物車 -->
<div class="cart-contain">
<div class="cart-table-container">
<div class="cart-filter-bar">
<span class="switch-cart">購物車(全部{{ cartTotalCount }})</span>
<!-- <div class="cart-sum" style="display: none">
<span class="pay-text">已選商品</span>
<span class="total-symbol">{{ cartTotalPrice }}</span>
<div class="pay-btn inactive-btn">結算</div>
</div> -->
</div>
<div class="cart-list-content">
<el-table
ref="cartTable"
:data="cartList"
v-loading="loading"
size="mini"
style="width: 95%; margin: 0 auto"
v-on:selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
align="center"
width="50"
></el-table-column>
<el-table-column label="商品圖檔" width="180">
<template slot-scope="scope">
<el-image
:src="scope.row.image"
style="width: 120px; height: 120px"
>
<div slot="placeholder" class="image-slot">
Loading<span class="dot">...</span>
</div>
<div slot="error" class="image-slot">
<el-image
style="width: 120px; height: 120px"
src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"
></el-image>
</div>
</el-image>
</template>
</el-table-column>
<el-table-column
label="商品名稱"
prop="productName"
></el-table-column>
<el-table-column label="單價" prop="price"></el-table-column>
<el-table-column label="數量" width="220">
<template slot-scope="scope">
<el-input-number
setp="1"
:min="1"
v-model="scope.row.num"
plain
v-on:change="calTotalPrice()"
></el-input-number>
</template>
</el-table-column>
<el-table-column label="金額">
<template slot-scope="scope">
<span>{{ scope.row.num * scope.row.price }}</span>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" align="center">
<template slot-scope="scope">
<el-button
size="medium"
type="danger"
v-on:click="delGood(scope.row.id)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="cart-filter-bar-bottom">
<div class="bar-bottom-left">
<span class="all-check">
<div>
<el-checkbox
class="all-check-checkbox"
v-model="isAllChecked"
v-on:change="checkAll"
>全選</el-checkbox
>
</div>
</span>
<span class="all-del" v-show="isAllChecked">
<el-button type="danger" size="small" v-on:click="delAll"
>删除</el-button
>
</span>
</div>
<div class="cart-sum">
<span class="pay-text">已選商品</span>
<span class="total-text">合計:</span>
<span class="total-symbol">{{ cartTotalPrice }}</span>
<div v-if="selectionData.length > 0" class="pay-btn-active">
結算
</div>
<div v-else class="pay-btn-inactive">結算</div>
</div>
</div>
</div>
</div>
</div>
<!-- 移動端樣式 -->
<div v-else class="cart-phone">
<!-- header
購物車清單
購物車操作欄 -->
<div v-if="cartList.length !== 0">
<div class="cart-box">
<div
v-for="(item, index) in cartList"
:key="index"
class="cart-list-item"
>
<div class="cart-item-info">
<div class="cart-item-left">
<div class="left-check" v-on:click="checkCurrent(item)">
<div class="checkbox">
<div v-if="item.checked" class="selected-check"></div>
<div v-else></div>
</div>
</div>
<el-image :src="item.image">
<div slot="placeholder" class="image-slot">
Loading<span class="dot">...</span>
</div>
<div slot="error" class="image-slot">
<el-image
fit="contain"
style="height: 100px"
src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"
></el-image>
</div>
</el-image>
</div>
<div class="cart-item-right">
<div class="cart-item-info-content">
<div class="goods-name">
{{ item.productName }}
</div>
<div class="numbers">
<div class="price">價格:{{ item.price * item.num }}</div>
</div>
</div>
<div class="cart-item-opera">
<el-input-number
setp="1"
:min="1"
v-model="item.num"
plain
v-on:change="calTotalPrice()"
></el-input-number>
</div>
</div>
</div>
<div class="del-btn" v-on:click="delGood(item.id)">
<span class="fa fa-trash-o"></span>
</div>
</div>
</div>
<!-- 全選 -->
<div class="bottom-all">
<div class="left">
<div class="left-check">
<el-checkbox
class="all-check-checkbox"
v-model="isAllChecked"
v-on:change="checkAll"
>全選</el-checkbox
>
</div>
<div class="del-text" v-show="isAllChecked" v-on:click="delAll">
删除
</div>
</div>
<div class="rights">
合計:
<span class="total-pay-count">{{ cartTotalPrice }}</span>
</div>
<div v-if="selectionData.length > 0" class="settlement-active">
結算
</div>
<div v-else class="settlement-inactive">結算</div>
</div>
</div>
<!-- 如果購物車沒有資料 -->
<div class="cart-no-data" v-if="cartList.length == 0">
<div>沒有資料</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "shopCart",
data() {
return {
//選中資料
selectionData: [],
// 購物車清單
cartList: [],
// 加載
loading: false,
// 購物車總數
cartTotalCount: 0,
// 購物車總價格
cartTotalPrice: 0.0,
// 是否是移動端
isMobile: false,
// 是否全選
isAllChecked: false,
};
},
created() {
let _this = this;
// 初始化資料
_this.initData();
},
mounted() {
let _this = this;
// 自适應
_this.resizeLayout();
window.onresize = function () {
_this.resizeLayout();
};
},
components: {},
methods: {
// 選擇目前商品
checkCurrent(item) {
let _this = this;
// 如果商品是被勾選的
if (item.checked) {
// 從被選擇數組中清除
_this.selectionData.forEach((sItem, sIndex) => {
if (sItem.id === item.id) {
_this.selectionData.splice(sIndex, 1);
}
});
// 勾選狀态變為false
_this.cartList.forEach((cItem, cIndex) => {
if (cItem.id === item.id) {
_this.cartList[cIndex]["checked"] = false;
}
});
} else {
// 如果商品是未被勾選的
// 勾選狀态變為true
_this.cartList.forEach((cItem, cIndex) => {
if (cItem.id === item.id) {
_this.cartList[cIndex]["checked"] = true;
}
});
// 添加到被選擇數組中
_this.selectionData.push(item);
}
// 如果被選擇數組沒有資料 則全選為false
if (_this.selectionData.length <= 0) {
_this.isAllChecked = false;
}
// 如果被選擇數組數組長度和購物車數組長度相同 則全選為true
if (_this.selectionData.length === _this.cartList.length) {
_this.isAllChecked = true;
}
// 計算商品總價和總數量
_this.calTotalPrice();
},
//響應式布局
resizeLayout() {
// 浏覽器寬
let width =
document.documentElement.offsetWidth || document.body.offsetWidth;
let height =
document.documentElement.clientHeight || document.body.clientHeight;
let _this = this;
if (width > 700) {
_this.isMobile = false;
} else {
_this.isMobile = true;
}
},
// 初始化資料
initData() {
let _this = this;
_this.getList();
},
// 擷取購物車清單
getList() {
let _this = this;
_this.cartList = [
{
id: "2142423",
image: "",
productName: "測試商品1",
// 單價
price: 12,
// 購買數量
num: 1,
// 如果api傳回的資料中沒有類似checked這種判斷是否選中的字段
// 可以在擷取收據後 初始化時周遊添加一遍
checked: false,
},
{
id: "2142423424",
image: "",
productName: "測試商品2",
price: 32,
num: 2,
checked: false,
},
];
},
// 計算總價和總數量
calTotalPrice() {
let _this = this;
_this.cartTotalPrice = 0;
_this.cartTotalCount = 0;
// 如果有選中項
if (_this.selectionData.length > 0) {
_this.selectionData.forEach((item) => {
_this.cartTotalPrice += item.num * item.price;
_this.cartTotalCount += item.num;
});
}
},
// 控制選擇商品
handleSelectionChange(data) {
let _this = this;
_this.selectionData = data;
// 這裡嵌套循環需要優化
_this.cartList.forEach((good) => {
if (_this.selectionData.length > 0) {
// 如果在被選擇數組中存在 則checked為true
_this.selectionData.forEach((selectedItem) => {
if (selectedItem.id === good.id) {
good.checked = true;
} else {
good.checked = false;
}
});
} else {
// 如果在被選擇數組中沒有資料則checked全設定為false
good.checked = false;
}
});
let cartTotalChecked = _this.selectionData.length;
if (_this.cartList.length === cartTotalChecked) {
_this.isAllChecked = true;
} else {
_this.isAllChecked = false;
}
_this.calTotalPrice();
},
// 全部删除
delAll() {
let _this = this;
_this
.$confirm("确定要删除全部商品嗎?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
// 這裡隻是前端删除
_this.cartList = [];
_this.isAllChecked = false;
// 删除後需要重新擷取資料重新整理頁面
// _this.getList();
})
.catch((e) => {
console.log(e);
});
},
// 單個删除
delGood(id) {
let _this = this;
if (!id) {
_this.$message.error("商品有誤,請重新整理後重試");
return;
}
_this
.$confirm("确定要删除此商品嗎?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
let goodIndex = 0;
_this.cartList.forEach((item, index) => {
if (item.id === id) {
goodIndex = index;
}
});
_this.cartList.splice(goodIndex, 1);
// _this.getList();
})
.catch((e) => {
console.log(e);
});
},
// 全選
checkAll() {
let _this = this;
// 如果全選
if (_this.isAllChecked) {
_this.getList();
// 将購物車清單複制給被選擇數組
_this.selectionData = JSON.parse(JSON.stringify(_this.cartList));
_this.cartList.forEach((cItem, cIndex) => {
_this.cartList[cIndex]["checked"] = true;
});
if (_this.$refs.cartTable) {
_this.$refs.cartTable.clearSelection();
// el table全部選中
_this.$refs.cartTable.toggleAllSelection();
}
} else {
_this.cartList.forEach((cItem, cIndex) => {
_this.cartList[cIndex]["checked"] = false;
});
_this.selectionData = [];
if (_this.$refs.cartTable) {
// el table清空選中
_this.$refs.cartTable.clearSelection();
}
}
_this.calTotalPrice();
},
},
};
</script>
<style>
/* 購物車web端 */
.cart-web {
width: 100%;
height: auto;
background: #e8e2e0;
}
/* 購物車移動端 */
.cart-phone {
width: 100%;
height: calc(100vh - 135px);
background: #e8e2e0;
}
/* 購物車頭部 */
.cart-header {
width: 100%;
height: 58px;
padding: 11px 0;
background-color: #fff;
display: flex;
justify-content: center;
}
.cart-header .cart-header-contain {
width: 80%;
display: flex;
align-items: center;
}
/* 購物車标題 */
.cart-header .cart-header-contain .cart-title {
font-size: 18px;
font-weight: 500;
}
.cart-contain {
width: 100%;
height: auto;
display: flex;
justify-content: center;
align-items: center;
padding-top: 24px;
}
.cart-table-container {
width: 80%;
border-radius: 25px;
padding: 10px 30px;
background: #fff;
min-height: calc(100vh - 130px);
position: relative;
}
.cart-filter-bar {
width: 100%;
display: flex;
justify-content: space-between;
}
.cart-filter-bar .switch-cart {
overflow: hidden;
color: #000;
font-size: 18px;
font-weight: 600;
height: 72px;
line-height: 72px;
}
.cart-filter-bar .cart-sum {
font-size: 14px;
display: flex;
align-items: center;
}
.cart-sum .total-symbol {
font-weight: 400;
margin-right: 12px;
font-size: 24px;
color: #ff5000;
}
/* 激活狀态的支付按鈕 */
.cart-sum .pay-btn-active {
width: 74px;
height: 42px;
line-height: 42px;
color: #fff;
background: #ff5000;
border-radius: 21px;
text-align: center;
cursor: pointer;
text-decoration: none;
font-size: 16px;
}
/* 未激活狀态的支付按鈕 */
.cart-sum .pay-btn-inactive {
width: 74px;
height: 42px;
line-height: 42px;
color: #fff;
background: #a3a3a3;
border-radius: 21px;
text-align: center;
cursor: not-allowed;
text-decoration: none;
font-size: 16px;
}
.inactive-btn {
background: #aaa !important;
color: #fff;
cursor: not-allowed !important;
}
.cart-list-content {
max-height: 100vh;
padding-bottom: 72px;
overflow-y: auto;
}
/* 購物車底部欄 */
.cart-filter-bar-bottom {
width: 95%;
display: flex;
justify-content: space-between;
position: absolute;
bottom: 0;
background: #fff;
z-index: 999;
}
.cart-filter-bar-bottom .bar-bottom-left {
display: flex;
justify-content: center;
align-items: center;
}
/* 全選 */
.cart-filter-bar-bottom .all-check {
overflow: hidden;
color: #000;
height: 72px;
line-height: 72px;
font-size: 12px;
}
.cart-filter-bar-bottom .all-check .all-check-checkbox {
margin-right: 10px;
}
/* 全部删除 */
.cart-filter-bar-bottom .all-del {
margin-left: 20px;
}
.cart-filter-bar-bottom .cart-sum {
font-size: 14px;
display: flex;
align-items: center;
}
.cart-sum .pay-text {
margin: 0 12px;
}
.cart-sum .total-text {
margin: 0 0 0 12px;
}
.cart-box {
padding: 10px 0;
}
.cart-list-item {
position: relative;
border-radius: 8px;
overflow: hidden;
border: 0;
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 20px;
background-color: #fff;
padding: 8px 0;
}
.cart-list-item .cart-item-info {
display: flex;
align-items: center;
padding: 0 0 0 15px;
}
.cart-list-item .cart-item-left {
width: 100px;
display: flex;
flex-direction: row;
align-items: center;
}
.cart-list-item .left-check {
display: flex;
align-items: center;
justify-content: center;
margin: 0 8%;
}
/* 單個選擇按鈕 */
.cart-list-item .left-check .checkbox {
width: 14px;
height: 14px;
border-radius: 50%;
background: #fff;
border: 1px solid #b9b9b9;
display: flex;
align-items: center;
justify-content: center;
}
/* 單個選擇按鈕選中 */
.cart-list-item .left-check .checkbox .selected-check {
width: 10px;
height: 10px;
border-radius: 50%;
background: red;
}
.cart-item-right {
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 10px;
}
.cart-item-opera {
display: flex;
align-items: center;
}
/* 删除按鈕 */
.del-btn {
position: absolute;
right: 10px;
bottom: 10px;
font-size: 17px;
color: red;
}
.cart-item-right .cart-item-info-content {
margin-right: 20px;
width: 70px;
}
.cart-item-right .goods-name {
width: 100%;
font-size: 15px;
color: #333333;
margin-top: 3px;
text-align: left;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.cart-item-right .numbers {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
}
.cart-item-right .numbers .price {
font-size: 14px;
line-height: 25px;
color: #ff0000;
}
.bottom-all {
height: 50px;
width: 100%;
padding: 0 2%;
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
position: fixed;
bottom: 0;
left: 0;
background-color: #fdfdfd;
z-index: 11;
border-top: 1px solid #f8f8f8;
}
.bottom-all .left {
float: left;
width: 28vw;
font-size: 14px;
position: relative;
}
.bottom-all .left .text {
position: absolute;
left: 35px;
top: 50%;
transform: translateY(-52%);
color: #333333;
}
.bottom-all .del-text {
color: red;
position: absolute;
left: 80px;
top: 47%;
transform: translateY(-52%);
}
.bottom-all .left-check {
padding-left: 8px;
flex-shrink: 0;
height: 50px;
margin-right: 8px;
align-items: center;
position: relative;
display: flex;
}
.bottom-all .rights {
width: 40vw;
line-height: 50px;
font-size: 16px;
text-align: center;
display: flex;
align-items: center;
justify-content: flex-end;
}
.bottom-all .settlement-inactive {
padding: 0 4px;
border-radius: 16px;
width: 18vw;
height: 35px;
line-height: 35px;
color: #ffffff;
font-size: 17px;
text-align: center;
margin-right: 20px;
cursor: not-allowed;
background-color: #a3a3a3;
}
.bottom-all .settlement-active {
padding: 0 4px;
border-radius: 16px;
width: 18vw;
height: 35px;
line-height: 35px;
color: #ffffff;
font-size: 17px;
text-align: center;
margin-right: 20px;
background-color: #ff5000;
}
/* 購物車為空的樣式 */
.cart-no-data {
text-align: center;
}
.total-pay-count {
font-size: 24px;
color: #ff5000;
}
@media (max-width: 700px) {
/* 彈窗 */
.el-message-box {
width: 300px !important;
}
/* el-input-number樣式 */
.el-input-number {
width: 100px !important;
line-height: 28px !important;
}
.el-input-number .el-input__inner {
padding-left: 0 !important;
padding-right: 0 !important;
}
.el-input__inner {
height: 30px !important;
}
.el-input-number__decrease,
.el-input-number__increase {
width: 20px !important;
}
}
</style>
項目代碼在下面
項目位址:https://gitee.com/joeyan3/joe-vue-demo-project.git