微信小程序–商品详情页面
包含功能点:
- 商品收藏
- 图片预览
- 客服
- 分享
- 加入购物车
- 跳转到购物车页面(
注意:open-type="switchTab"
)
结构:goods_detail.wxml
<!-- 轮播图 -->
<view class="detail_swiper">
<swiper autoplay="{{true}}" circular="{{true}}" indicator-dots="{{true}}">
<swiper-item wx:for="{{goodsObj.pics}}" wx:key="pics_id" bindtap="handlePrevewImage" data-url="{{item.pics_mid}}">
<image src="{{item.pics_mid}}" mode="widthFix" />
</swiper-item>
</swiper>
</view>
<!-- 商品价格 -->
<view class="goods_price">¥{{goodsObj.goods_price}}</view>
<!-- 商品名称和收藏 -->
<view class="goods_name_row">
<view class="goods_name">{{goodsObj.goods_name}}{{goodsObj.goods_name}}</view>
<view class="goods_collect" bindtap="handleCollect">
<text class="iconfont {{isCollect?'icon-shoucang1':'icon-shoucang'}}"></text>
<view class="collect_text">收藏</view>
</view>
</view>
<!-- 商品详情 -->
<view class="goods_info">
<view class="goods_info_title">图文详情</view>
<view class="goods_info_content">
<!-- 富文本:可以渲染后台返回的标签字符串 -->
<rich-text nodes="{{goodsObj.goods_introduce}}"></rich-text>
</view>
</view>
<!-- 底部tab栏 -->
<view class="btm_tool">
<view class="tool_item">
<view class="iconfont icon-kefu"></view>
<view>客服</view>
<button open-type="contact"></button>
</view>
<view class="tool_item">
<view class="iconfont icon-fenxiang"></view>
<view>分享</view>
<button open-type="share"></button>
</view>
<navigator class="tool_item" url="/pages/cart/cart" open-type="switchTab">
<view class="iconfont icon-gouwuche"></view>
<view>购物车</view>
</navigator>
<view class="tool_item btn_cart" bindtap="handleCartAdd">加入购物车</view>
<view class="tool_item btn_buy">立即购买</view>
</view>
样式:goods_detail.less
// 底部tab栏:固定定位--遮挡内容
page {
padding-bottom: 90rpx;
}
// 轮播图
.detail_swiper {
// 原图:400 * 400px,比例:1-1
swiper {
// 高 = 宽,也是比例:1-1;根据需要微调为65vw(该写:100vw)
height: 65vw;
text-align: center;
swiper-item {
image {
width: 60%;
}
}
}
}
// 商品价格
.goods_price {
padding: 15rpx;
font-size: 32rpx;
font-weight: 600;
color: var(--themeColor);
}
// 商品名称和收藏
.goods_name_row {
border-top: 5rpx solid #dedede;
border-bottom: 5rpx solid #dedede;
padding: 10rpx 0;
display: flex;
.goods_name {
flex: 5;
color: #000;
font-style: 30rpx;
padding: 0 10rpx;
// 文字溢出--省略号代替...
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.goods_collect {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-left: 1rpx solid #000;
.icon-shoucang1 {
color: orangered;
}
.collect_text {}
}
}
// 商品详情
.goods_info {
.goods_info_title {
font-size: 32rpx;
font-weight: 600;
color: var(--themeColor);
padding: 20rpx;
}
.goods_info_content {}
}
// 底部tab栏
.btm_tool {
position: fixed;
left: 0;
bottom: 0;
// 块级元素:添加绝对、固定定位之后,需要给一个宽度;否则宽度由内容撑开了
width: 100%;
height: 90rpx;
background-color: #fff;
border-top: 1rpx solid #ccc;
display: flex;
.tool_item {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 24rpx;
position: relative;
// 隐形的button按钮:绝对定位,继承父元素宽高,不透明
button {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
}
.btn_cart {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex: 2;
background-color: #ffa500;
color: #fff;
font-size: 30rpx;
font-weight: 600;
}
.btn_buy {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex: 2;
background-color: #eb4450;
color: #fff;
font-size: 30rpx;
font-weight: 600;
}
}
逻辑:goods_detail.js文件
// pages/goods_detail/goods_detail.js
import { request } from "../../request/index.js";
Page({
/**
* 页面的初始数据
*/
data: {
// 接口:商品详情数据
goodsObj: {},
// 商品是否被收藏
isCollect: false
},
// 商品对象--全局变量
GoodsInfo: {},
// 点击轮播图 放大预览
handlePrevewImage(e) {
// 1.先构造要预览的图片数组
const urls = this.GoodsInfo.pics.map(v => v.pics_mid);
// 2.接收传递过来的图片url
const current = e.currentTarget.dataset.url;
wx.previewImage({
current,
urls,
success: (result) => {
console.log(result)
}
});
},
// 点击 加入购物车
handleCartAdd() {
// 1.获取缓存中的购物车 数组格式
let cart = wx.getStorageSync("cart") || [];
// 2.先判断 当前的商品是否已经存在于 购物车 (缓存中的商品id === 商品对象的id)
let index = cart.findIndex(v => v.goods_id === this.GoodsInfo.goods_id);
if (index === -1) {
// 3. 不存在于购物车的数组中 直接给购物车数组添加一个新元素 新元素带上购买数量属性 num 重新把购物车数组 填充回缓存中
this.GoodsInfo.num = 1;
// 重点:添加属性--商品选中状态--为购物车页面准备
this.GoodsInfo.checked = true;
cart.push(this.GoodsInfo)
} else {
// 4. 已经存在 修改商品数据 执行购物车数量++ 重新把购物车数组 填充回缓存中
cart[index].num++;
}
// 5. 不管该商品是否存在于购物车数组中,都需要把购物车数组填充回缓存中
wx.setStorageSync("cart", cart);
// 6. 弹框提示
wx.showToast({
title: '加入成功',
icon: 'success',
// 防止用户手抖 疯狂点击按钮
mask: true
});
},
// 获取商品详情数据
getGoodsDetail(goods_id) {
request({ url: "/goods/detail", data: { goods_id } }).then(goodsObj=>{
// 将接口数据赋值给全局变量
this.GoodsInfo = goodsObj;
// 1.获取缓存中的商品收藏的按钮
let collect = wx.getStorageSync("collect") || [];
// 2.判断当前商品是否被收藏
let isCollect = collect.some(v => v.goods_id === this.GoodsInfo.goods_id);
// 3. 提取有用信息
this.setData({
goodsObj: {
goods_name: goodsObj.goods_name,
goods_price: goodsObj.goods_price,
/**
* iphone 部分手机 不识别webp图片格式
* 最好找到后台 让他做修改
* 临时自己修改 确保后台存在 1.webp => 1.jpg
*/
goods_introduce: goodsObj.goods_introduce.replace(/\.webp/g, '.jpg'),
pics: goodsObj.pics
},
isCollect
})
});
},
/**
* 点击收藏按钮
* 1. 判断该商品是否存在于缓存数组中
* 2. 已经存在 把该商品删除
* 3. 没有存在 把该商品添加到收藏数组中 存入缓存中即可。
*/
handleCollect() {
// 默认:没有被收藏
let isCollect = false;
// 1.获取缓存中的商品收藏数组
let collect = wx.getStorageSync("collect") || [];
// 2.判断该商品是否被收藏过
let index = collect.findIndex(v => v.goods_id === this.GoodsInfo.goods_id);
// 3.当index!= -1 表示 已经收藏过了
if (index !== -1) {
// 能找到 已经收藏过了 在数组中删除该商品
collect.splice(index, 1);
// 取消收藏
isCollect = false;
wx.showToast({
title: '取消成功',
icon: 'success',
mask: true
});
}else {
// 没有收藏过
collect.push(this.GoodsInfo)
// 添加收藏
isCollect = true;
wx.showToast({
title: '收藏成功',
icon: 'success',
mask: true
});
}
// 4.把数组存入缓存中
wx.setStorageSync("collect", collect);
// 5.修改data中的数据
this.setData({
isCollect
})
},
/**
* 生命周期函数--监听页面显示
*/
onLoad: function (options) {
console.log(options.goods_id)
},
/**
* 生命周期函数--监听页面显示
*
* 页面 onShow 的时候:收藏逻辑放在了 this.getGoodsDetail() 函数里面
* 1. 加载缓存中的商品收藏的数据
* 2. 判断当前商品是不是被收藏
* 是 改变页面的图标
* 不是 继续执行下面操作
*/
onShow: function (options) {
// 获取页面栈
let pages = getCurrentPages();
// 获取当前页面
let currentPages = pages[pages.length - 1]
// 获取url中传递过来的参数
const { goods_id } = currentPages.options;
// 发请求获取该商品的详情信息
this.getGoodsDetail(goods_id)
}
})
页面配置文件:goods_detail.json文件
{
"usingComponents": {},
"navigationBarTitleText": "商品详情"
}