繼續完善訂單頁面。
這裏需要將一些方法進行抽離。
src\effects\cartEffects.js
import { computed } from 'vue'
import { useStore } from 'vuex'
// 添加、減少到購物車功能
export const useCommonCartEffect = shopId => {
const store = useStore()
const cartList = store.state.cartList // 加入購物車的商品
/**
* 加入或減少購物車數量
* @param {String} shopId 店鋪id
* @param {String} productId 商品id
* @param {Object} productInfo 商品信息集
* @param {Number} num 加入購物車的數量
*/
const changeCartItemInfo = (shopId, productId, productInfo, num) => {
console.log(
'changeCartItemInfo:',
'shopId:' + shopId,
'productId:' + productId,
'productInfo:' + JSON.stringify(productInfo),
'num:' + num
)
// 更新vuex中的值
store.commit('changeItemToCart', { shopId, productId, productInfo, num })
}
// 獲得加入購物車商品的信息集
const productList = computed(() => {
const productInfoList = cartList[shopId]?.productList || [] // 不存在默認空數組
return productInfoList
})
// 獲得商鋪名稱
const shopName = computed(() => {
const shopName = cartList[shopId]?.shopName || '' // 不存在默認空數組
return shopName
})
// 計算shopId下所有cartList的商品數量total、價錢之和totalPrice
const calculations = computed(() => {
const productList = cartList[shopId]?.productList
const resultData = {
// 總商品數量
total: 0,
// 總金額
totalPrice: 0,
// 全選
isAllChecked: true
}
if (productList) {
for (const i in productList) {
const product = productList[i]
// 總商品數量
resultData.total += product.count
// 總金額
if (product.checked === true) {
resultData.totalPrice += product.count * product.price
}
// 全選
if (product.count > 0 && !product.checked) {
resultData.isAllChecked = false
}
}
resultData.totalPrice = resultData.totalPrice.toFixed(2) // 保留2位小數
}
return resultData
})
// const total = computed(() => {
// const productList = cartList[shopId]?.productList
// let count = 0
// if (productList) {
// for (const i in productList) {
// const product = productList[i]
// count += product.count
// }
// }
// return count
// })
// const totalPrice = computed(() => {
// const productList = cartList[shopId]?.productList
// let count = 0
// if (productList) {
// for (const i in productList) {
// const product = productList[i]
// if (product.checked === true) {
// count += product.count * product.price
// }
// }
// }
// return count.toFixed(2) // 保留2位小數
// })
// 全選的計算屬性
// const allChecked = computed(() => {
// const productList = cartList[shopId]?.productList
// let result = true
// if (productList) {
// for (const i in productList) {
// const product = productList[i]
// if (product.count > 0 && !product.checked) {
// result = false
// break
// }
// }
// }
// return result
// })
return { cartList, shopName, calculations, productList, changeCartItemInfo }
}
這樣,src\views\shop\Cart.vue做了減法:
......
<script>
import { ref } from 'vue'
import { useRoute } from 'vue-router' // 路由跳轉方法
import { useStore } from 'vuex' // 路由跳轉方法
import { useCommonCartEffect } from '@/effects/cartEffects'
const useCartEffect = shopId => {
const store = useStore()
const { cartList, productList, changeCartItemInfo, calculations } = useCommonCartEffect(
shopId
)
const getProductCartCount = (shopId, productId) => {
return cartList?.[shopId]?.productList?.[productId]?.count || 0
}
// 單個勾選或者不勾選
const changeCartItemChecked = (shopId, productId) => {
store.commit('changeItemChecked', { shopId, productId })
}
// 清除購物車按鈕
const cleanCartProducts = shopId => {
store.commit('changeCleanCartProducts', { shopId })
}
// 購物車全選或者取消全選
const setCartItemsChecked = shopId => {
store.commit('setCartItemsChecked', { shopId })
}
return {
cartList,
calculations,
productList,
changeCartItemChecked,
changeCartItemInfo,
cleanCartProducts,
getProductCartCount,
setCartItemsChecked
}
}
// 展示隱藏購物車
const toggleCartEffect = () => {
const showCart = ref(false)
// 顯示隱藏購物車具體內容
const handleCartShowChange = () => {
showCart.value = !showCart.value
}
return { showCart, handleCartShowChange }
}
export default {
name: 'Cart',
setup() {
const route = useRoute()
const shopId = route.params.id // 店鋪id
// 展示隱藏購物車
const { showCart, handleCartShowChange } = toggleCartEffect()
// 計算總價和加入購物車的總數量
const {
cartList,
calculations,
productList,
changeCartItemChecked,
changeCartItemInfo,
cleanCartProducts,
getProductCartCount,
setCartItemsChecked
} = useCartEffect(shopId)
return {
cartList,
calculations,
productList,
shopId,
showCart,
handleCartShowChange,
changeCartItemChecked,
changeCartItemInfo,
cleanCartProducts,
getProductCartCount,
setCartItemsChecked
}
}
}
</script>
......
進一步完善src\views\orderConfirmation\OrderConfirmation.vue
<template>
<div class="wrapper">
<div class="top">
<div class="top__bgcolor" />
<div class="top__header">
<div class="top__header__back" @click="handleBackClick">
<i class="custom-icon custom-icon-back"></i>
</div>
<span>確認訂單</span>
</div>
<div class="top__receiver">
<div class="top__receiver__title">收貨地址</div>
<div class="top__receiver__address">
西安一二三大學四五六科技園2號樓
</div>
<div class="top__receiver__info">
<span class="top__receiver__info__name">張三(先生)</span>
<span class="top__receiver__info__phone">18012341234</span>
</div>
<div class="top__receiver__icon">
<i class="custom-icon custom-icon-back"></i>
</div>
</div>
</div>
<div class="products">
<div class="products__title">{{shopName}}</div>
<div>
<div class="products__item" v-for="item in productList" :key="item._id">
<img class="products__item__img" :src="item.imgUrl" />
<div class="products__item__detail">
<h4 class="products__item__title">{{ item.name }}</h4>
<p class="products__item__price">
<span>
<span class="products__item__yen"> ¥ </span>
{{ item.price }}×{{item.count}}
</span>
<span class="products__item__total">
<span class="products__item__yen"> ¥ </span>
{{( item.price*item.count ).toFixed(2)}}
</span>
</p>
</div>
</div>
</div>
</div>
<div class="order">
<div class="order__price">
實付金額 ¥<b>{{calculations.totalPrice}}</b>
</div>
<div class="order__btn">
<!-- <router-link :to="{ path: `/orderConfirmation/${shopId}` }"> -->
提交訂單
<!-- </router-link> -->
</div>
</div>
</div>
</template>
<script>
// import { ref } from 'vue'
import { useCommonCartEffect } from '@/effects/cartEffects'
import { useRoute, useRouter } from 'vue-router' // 路由跳轉方法
export default {
name: 'OrderConfirmation',
setup() {
const route = useRoute()
const router = useRouter()
const shopId = route.params.shopId // 店鋪id
const { shopName, productList, calculations } = useCommonCartEffect(shopId)
const handleBackClick = () => {
router.back()
}
return {
shopName,
productList,
calculations,
handleBackClick
}
}
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
@import '@/style/mixins.scss';
.wrapper {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #eee;
overflow-y: scroll; //防止超出屏幕
}
.top {
position: relative;
height: 1.96rem;
background-size: 100% 1.59rem;
/* 漸變軸爲0度,相當於從下到上,
高度4%位置從rgba(0, 145, 255, 0) 開始漸變
到高度50%位置的藍色(#0091ff)結束 */
background-image: linear-gradient(0deg, rgba(0, 145, 255, 0) 4%, #0091ff 50%);
background-repeat: no-repeat;
&__header {
position: relative;
padding-top: 0.26rem;
line-height: 0.24rem;
color: #fff;
text-align: center;
font-size: 0.16rem;
&__back {
position: absolute;
font-size: 0.22rem;
left: 0.18rem;
}
}
&__receiver {
position: absolute;
left: 0.18rem;
right: 0.18rem;
bottom: 0rem;
height: 1.11rem;
background: #fff;
border-radius: 0.04rem;
&__title {
line-height: 0.22rem;
padding: 0.16rem 0 0.14rem 0.16rem;
font-size: 0.16rem;
color: #333;
}
&__address {
line-height: 0.2rem;
padding: 0 0.4rem 0 0.16rem;
font-size: 0.16rem;
color: #333;
}
&__info {
padding: 0.06rem 0 0 0.16rem;
&__name &__phone {
margin-right: 0.1rem;
line-height: 0.18rem;
font-size: 0.12rem;
color: #666;
}
}
&__icon {
//旋轉180度
transform: rotate(180deg);
position: absolute;
right: 0.16rem;
top: 0.53rem;
font-size: 0.16rem;
color: #666;
}
}
}
.products {
margin: 0.16rem 0.18rem 0.2rem 0.18rem;
background: #fff;
&__title {
padding: 0.16rem 0.16rem 0 0.16rem;
font-size: 0.16rem;
color: #333;
}
&__item {
position: relative;
display: flex;
padding: 0.16rem;
&__img {
width: 0.46rem;
height: 0.46rem;
margin-right: 0.16rem;
}
// 配合解決超出長度以省略號顯示而不會出現換行
&__detail {
overflow: hidden;
flex: 1;
}
&__title {
margin: 0;
line-height: 0.2rem;
font-size: 0.14rem;
color: $content-font-color;
// 超出長度以省略號顯示而不會出現換行
@include ellipsis;
}
&__price {
display: flex;
margin: 0.06rem 0 0 0;
line-height: 0.2rem;
font-size: 0.14rem;
color: $height-light-font-color;
}
&__total {
text-align: right;
color: #000;
flex: 1;
}
&__yen {
font-size: 0.12rem;
}
}
}
.order {
position: absolute;
left: 0;
right: 0;
bottom: 0;
display: flex;
box-sizing: border-box; //往內塞入border
line-height: 0.49rem;
height: 0.49rem;
border-top: 0.01rem solid $content-bg-color;
background: $bg-color;
&__price {
flex: 1;
text-indent: 0.24rem;
font-size: 0.14rem;
color: #333;
}
&__btn {
width: 0.98rem;
background-color: #4fb0f9;
text-align: center;
color: $bg-color;
font-size: 0.14rem;
// 去掉a標籤的下劃線
a {
color: $bg-color;
text-decoration: none; //去掉文本修飾
}
}
}
</style>
效果如下:
此時在瀏覽器進行如下的操作:
發現當商品很多時,還是會被撐開。
進一步完善:
......
<div class="products">
<div class="products__title">{{shopName}}</div>
<div class="products__list">
......
</div>
</div>
......
<style lang="scss" scoped>
......
.products {
......
&__title {
......
}
&__list {
position: absolute;
left: 0;
right: 0;
bottom: 0.6rem;
top: 2.06rem;
}
......
}
......
</style>
繼續完善css
&__list {
overflow-y: scroll;
position: absolute;
left: 0;
right: 0;
bottom: 0.6rem;
top: 2.05rem;
}
發現滾動效果出來了。繼續嘗試調試:
&__list {
overflow-y: scroll;
position: absolute;
padding: 0 0.16rem;
left: 0;
right: 0;
bottom: 0.6rem;
top: 2.46rem;
background: #fff;
}
效果很接近。繼續調試:
&__list {
overflow-y: scroll;
position: absolute;
margin: 0 0.18rem;
left: 0;
right: 0;
bottom: 0.6rem;
top: 2.46rem;
background: #fff;
}
到這裏我們想要的效果基本都出來了。
繼續微調優化:
.products {
......
&__title {
......
}
&__list {
......
}
&__item {
position: relative;
display: flex;
padding: 0.16rem 0.16rem 0 0.16rem;
......
}
}
當元素很多的時候,這樣效果已經很好了,但當元素較少時,就會如下樣式:
解決辦法:創建一個wrapper容器包裹list,然後通過list的背景色自動撐開容器。
......
<div class="products">
<div class="products__title">{{shopName}}</div>
<div class="products__wrapper">
<div class="products__list">
......
</div>
</div>
</div>
......
<style lang="scss" scoped>
......
.products {
margin: 0.16rem 0.18rem 0.2rem 0.18rem;
background: #fff;
&__title {
padding: 0.16rem;
font-size: 0.16rem;
color: #333;
}
// list外層的wrapper容器
&__wrapper {
overflow-y: scroll;
position: absolute;
margin: 0 0.18rem;
left: 0;
right: 0;
bottom: 0.6rem;
top: 2.6rem;
}
&__list {
background: #fff;
}
&__item {
......
padding: 0 0.16rem 0.16rem 0.16rem;
......
}
}
......
</style>
這樣效果就出來了。
完善邏輯:
<div class="products">
<div class="products__title">{{shopName}}</div>
<div class="products__wrapper">
<div class="products__list">
<template v-for="item in productList" :key="item._id">
<div class="products__item" v-if="item.count>0">
......
</div>
</template>
</div>
</div>
</div>
順便修復一下之前的一個bug:
src\store\index.js
/**
* 加入或減少購物車數量
* @param {*} state
* @param {String} shopId 店鋪id
* @param {String} productId 商品id
* @param {Object} productInfo 商品信息集
* @param {Number} num 加入購物車的數量
* @param {*} payload
*/
changeItemToCart(state, payload) {
......
product.count <= 0 && (shopInfo.productList[productId].count = 0)
......
},
12-7