1.前页点击商品,通过 uni.navigateTo({url: “/pages/list/index?query=”+this.keyword}),api,传递商品数据,进入详情组件,依然是onLoad()接受数据,发送请求,将请求的信息渲染出来。
2.点击客服,弹出客服聊天框,这里用按钮设置open-type="contact"即可。
3.点击购物车正常思路:1:未登陆就跳到登陆。2:未登陆就将数据存到本地,到登陆时从本地读取。
4.点击加入购物车,从当前商品信息解构出商品的信息,商品id.for循环判断购物车数组是否存在该商品id.存在则商品数量加一,而且自定义状态为选择goods—checked=true, uni.setStorageSync(“carts”, this.carts);不存在就将商品信息添加进购物车数组并数量设置为1.说白了就是本地存储前判断有无该商品。
5.点击购物车,跳转到购物车页面,用uni.getStorageSync取出本地存储的商品,循环本地存储的商品列表。渲染到购物车页面,点击增减,传递购物车列表的index和step
6.并重新给商品列表索引为index的项的goods-number赋值;点击选择框,状态改变,选中框颜色也改变。通过计算属性过滤出选中的商品。
7.计算属性判断选中的和购物车列表数组长度是否相等,如果相等,则全选按钮的:color颜色为选中,全选控制单选:for循环,将商品的按钮设置为true;
8.金额计算通过计算属性,数量乘以单价。数据持久化:数量变化或者选中状态变化时,更新本地存储,重新将购物车列表存一次。
9.收货地址调用api, uni.chooseAddress({ success: (info) => {this.address = info;}, });如果成功,赋值该地址给data里的地址。渲染到地址上。
详情页:
点击购物车后的购物车页面:
代码如下:
<template>
<view class="wrapper">
<!-- 商品图片 -->
<swiper
class="pics"
indicator-dots
indicator-color="rgba(255, 255, 255, 0.6)"
indicator-active-color="#fff"
>
<swiper-item :key="pic.pics_id" v-for="pic in goods.pics">
<image :src="pic.pics_mid"></image>
</swiper-item>
</swiper>
<!-- 基本信息 -->
<view class="meta">
<view class="price">¥{{ goods.goods_price }}</view>
<view class="name">{{ goods.goods_name }}</view>
<view class="shipment">快递: 免运费</view>
<text class="collect icon-star">收藏</text>
</view>
<!-- 商品详情 -->
<view class="detail">
<!-- <rich-text :nodes="goods.goods_introduce"></rich-text> -->
<view v-html="goods.goods_introduce"></view>
</view>
<!-- 操作 -->
<view class="action">
<button open-type="contact" class="icon-handset">
联系客服
</button>
<text class="cart icon-cart" @click="goCart">购物车</text>
<text @click="addCart" class="add">加入购物车</text>
<text class="buy" @click="createOrder">立即购买</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
params: null,
goods: null,
carts: uni.getStorageSync("carts") || [],
};
},
methods: {
// 加入购物车
addCart() {
let { goods_id, goods_name, goods_price, goods_small_logo } = this.goods;
let flag = false;
this.carts.forEach((item) => {
if (item.goods_id === goods_id) {
flag = true;
item.goods_number += 1;
return;
}
});
if (!flag) {
this.carts.push({
goods_id,
goods_name,
goods_price,
goods_small_logo,
goods_number: 1,
goods_checked: true,
});
}
uni.setStorageSync("carts", this.carts);
uni.showToast({ title: "加入成功" });
},
// 购物车
goCart() {
uni.switchTab({
url: "/pages/index/shop",
});
},
async getDetail() {
const res = await this.http({
url: "/api/public/v1/goods/detail",
data: {
goods_id: this.params,
},
});
// console.log(res[1].data.message);
this.goods = res[1].data.message;
},
},
onLoad(e) {
this.params = e.goods_id;
this.getDetail();
},
};
</script>
<style scoped lang="less">
.wrapper {
margin-bottom: 100rpx;
background-color: #f4f4f4;
}
.pics {
height: 640rpx;
}
.meta {
height: 250rpx;
line-height: 1;
padding: 30rpx 180rpx 30rpx 20rpx;
box-sizing: border-box;
background-color: #fff;
position: relative;
.price {
font-size: 36rpx;
color: #ea4451;
margin-bottom: 20rpx;
}
.name {
color: #333;
line-height: 1.4;
font-size: 33rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.shipment {
font-size: 27rpx;
color: #999;
position: absolute;
bottom: 30rpx;
}
.collect {
width: 140rpx;
height: 88rpx;
text-align: center;
box-sizing: border-box;
border-left: 1rpx solid #ddd;
font-size: 24rpx;
color: #999;
position: absolute;
right: 10rpx;
top: 91rpx;
}
[class*="icon-"]::before {
display: block;
font-size: 45rpx;
margin-bottom: 10rpx;
}
}
.detail image {
width: 100%;
height: 480rpx;
margin-top: 20rpx;
}
.action {
width: 100%;
height: 98rpx;
background-color: #fff;
position: fixed;
left: 0;
bottom: 0;
display: flex;
align-items: center;
text {
display: block;
}
.add,
.buy {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
width: 210rpx;
text-align: center;
font-size: 27rpx;
color: #fff;
}
.add {
background-color: #f4b73f;
}
.buy {
background-color: #ea4451;
}
button {
padding: 0;
border-radius: 0;
background-color: #fff;
&::after {
border: none;
}
}
button,
.cart {
flex: 1;
text-align: center;
color: #989898;
font-size: 24rpx;
box-sizing: border-box;
}
[class*="icon"]::before {
display: block;
font-size: 45rpx;
margin-bottom: 2rpx;
}
}
</style>