微信小程序开发一个小型商城(六、购物车页面)
上一篇文章:微信小程序开发一个小型商城(五、商品详情)当我们在商品详情界面中点击添加购物后,会跳转到购物车界面,购物车界面是一个tabbar,在跳转的时候需要加上ope-type。看下购物车的静态页面把:如下图页面分析:在最上面需要获取收货地址:当存在则显示信息,不存在的时候显示一个按钮表示要用户授权。下面是类似与goodlist的一个个的小商品块,再下面就类似与goods_detail当中...
上一篇文章:微信小程序开发一个小型商城(五、商品详情)
当我们在商品详情界面中点击添加购物后,会跳转到购物车界面,购物车界面是一个tabbar,在跳转的时候需要加上ope-type。看下购物车的静态页面把:如下图
页面分析:在最上面需要获取收货地址:当存在则显示信息,不存在的时候显示一个按钮表示要用户授权。下面是类似与goodlist的一个个的小商品块,再下面就类似与goods_detail当中的加入购物车那一栏。
获取用户授权,显示地址
使用wx:if else进行判断显示哪一个(授权按钮还是信息)
<view class="revice_address_row">
<view class="address_btn" wx:if="{{!address.userName}}">
<button bindtap="handleChooseAddress" type="primary" plain>获取收货地址</button>
</view>
<!-- 当收货地址 存在 详细信息就显示 -->
<view wx:else class="user_info_row">
<view class="user_info">
<view>{{address.userName}}</view>
<view>{{address.provinceName}}{{address.cityName}}{{address.countyName}}{{address.countyName}}{{address.detailInfo}}</view>
</view>
<view class="user_phone">{{address.telNumber}}</view>
</view></view>
给按钮和信息加上些许样式:
.revice_address_row {
.address_btn {
padding: 20rpx;
button {
width: 60%;
}
}
.user_info_row {
display: flex;
padding: 20rpx;
.user_info {
flex: 5;
}
.user_phone {
flex: 3;
text-align: right;
}}}
商品的购买列表
先写上一个购物车,商品列表可以从good_list里面照搬一些。以及当商品为空时,同样用wx:if else 进行判断,为空后使用一种外网图片进行替换。
<view class="cart_content">
<view class="cart_title">购物车</view>
<view class="cart_main">
<!--当cart数组不为0显示 -->
<block wx:if="{{cart.length!==0}}">
<view class="cart_item" wx:for="{{cart}}" wx:key="goods_id">
<!--复选框-->
<view class="cart_chk_wrap">
<checkbox-group bindtap="handleItemChange" data-id="{{item.goods_id}}">
<checkbox checked="{{item.checked}}"></checkbox>
</checkbox-group>
</view>
<!--商品图片-->
<navigator class="cart_img_wrap">
<image src="{{item.goods_small_logo}}" mode="widthFix" />
</navigator>
<!--商品信息-->
<view class="cart_info_wrap">
<view class="goods_name">
{{item.goods_name}}
</view>
<view class="goods_price_wrap">
<view class="goods_price">¥{{item.goods_price}}</view>
<view class="cart_num_tool">
<view class="num_edit" bindtap="handleItemNumEdit" data-id="{{item.goods_id}}" data-operation="{{-1}}">-</view>
<view class="goods_num">{{item.num}}</view>
<view class="num_edit" bindtap="handleItemNumEdit" data-id="{{item.goods_id}}" data-operation="{{1}}">+</view>
</view>
</view>
</view>
</view>
</block>
<block wx:else>
<image src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3559485588,3499568517&fm=15&gp=0.jpg" mode="widthFix" />
</block>
</view>
</view>
同理goodslist界面,加上样式,多了一个复选框。使复选框居中显示。
.cart_content {
.cart_title {
padding: 20rpx;
color: var(--themeColor);
font-size: 36rpx;
border-top: 1px solid currentColor;
border-bottom: 1px solid currentColor;
}
.cart_main {
.cart_item {
display: flex;
padding: 10rpx;
border-bottom: 1px solid #ccc;
.cart_chk_wrap {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
checkbox-group {
checkbox {
}
}
}
.cart_img_wrap {
flex: 2;
display: flex;
justify-content: center;
align-items: center;
image {
width: 80%;
} }
.cart_info_wrap {
flex: 4;
display: flex;
flex-direction: column;
justify-content: space-around;
.goods_name {
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: #666;
}
.goods_price_wrap {
display: flex;
justify-content: space-between;
.goods_price {
color: var(--themeColor);
font-size: 34rpx;
}
.cart_num_tool {
display: flex;
.num_edit {
width: 50rpx;
height: 50rpx;
display: flex;
justify-content: center;
align-items: center;
border: 1rpx solid #ccc;
}
.goods_num {
width: 50rpx;
height: 50rpx;
display: flex;
justify-content: center;
align-items: center;}}}}}}}
立即购买
一个单纯的view,加上颜色等:以及绝对定位
<view class="footer_tool">
<!--全选-->
<veiw class="all_chk_wrap">
<checkbox-group bindchange="handleItemAllchange">
<checkbox checked="{{allchecked}}">全选</checkbox>
</checkbox-group>
</veiw>
<!--总价格-->
<view class="total_price_wrap">
<view class="total_price">合计
<text class="total_price_text">¥{{totalPrice}}</text>
</view>
<view>包含运费</view>
</view>
<!--结算-->
<view class="order_pay_wrap" bindtap="handlePay">结算({{totalNum}})</view>
</view>
样式文件
.footer_tool {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 90rpx;
background-color: #fff;
display: flex;
border-top: 1px solid #ccc;
.all_chk_wrap {
flex: 2;
display: flex;
align-items: center;
justify-content: center;
}
.total_price_wrap {
flex: 4;
padding-left: 15rpx;
.total_price {
.total_price_text {
color: var(--themeColor);
font-size: 34rpx;
font-weight: 600;
}
}
}
.order_pay_wrap {
flex: 3;
background-color: var(--themeColor);
font-size: 32rpx;
font-weight: 600;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
}
js文件动态获取数据及渲染
页面整合
在这个页面当中会发现会使用到很多的内置api以及方法,将这些方法进行封装以下,提升代码的性能:在util文件夹下新建一个文件ansycWx.js
文件中代码如下所示:为例不让文章显得太过长就把代码格式弄了一下,复制代码后可重新整理代码格式。
export const getSetting = () => {
return new Promise((resolve, reject) => {
wx.getSetting({
success: (result) => {resolve(result);},
fail: (err) => {reject(err);},
});
});
};
export const chooseAddress = () => {
return new Promise((resolve, reject) => {
wx.chooseAddress({
success: (result) => {resolve(result);},
fail: (err) => {reject(err);},
});
});
};
export const openSetting = () => {
return new Promise((resolve, reject) => {
wx.openSetting({
success: (result) => {resolve(result);},
fail: (err) => {reject(err);},
});
});
};
export const login = () => {
return new Promise((resolve, reject) => {
wx.login({
timeout: 10000,
success: (result) => {resolve(result);},
fail: (err) => {reject(err);},
});
});
};
export const requestPayment = (pay) => {
return new Promise((resolve, reject) => {
wx.requestPayment({
...pay,
success: (result) => {resolve(result)},
fail: (err) => {reject(err)},
});
});
};
index.js文件
在编写之前将文件进行导入:如下代码所示:
import { request } from "../../request/index.js";
import regeneratorRuntime from "../../lib/runtime/runtime";
import { getSetting, chooseAddress, openSetting } from "../../util/ansycWx.js";
在data属性中定义变量:
address: {}, //地址信息
cart: [], //购物车数组
allchecked: false, //全部选中
totalPrice: 0, //总价
totalNum: 0, //总数量
首先就是调用获取地址的api,获取值后将值进行设为缓存,再者在wxml文件当中就可以对值进行获取,并判断:
async handleChooseAddress(e) {
console.log("获取地址");
try {
//获取授权状态
const res1 = await getSetting();
const scopeAddress = res1.authSetting["scope.address"];
//判断授权状态
if (scopeAddress === false) {
await openSetting();
}
//调用api
const address = await chooseAddress();
//把值设置到缓存当中。
wx.setStorageSync("address", address);
} catch (error) {
console.log(error);
}
},
在这个页面当中存在数据时刻独秀要进行修改,将这些代码抽离出来,使用一个新的方法进行封装。也就是对购物车当中的数据,有商品数据、是否选中。
setCart(cart) {
let allchecked = true;
//申明总价格和总数量
let totalPrice = 0;
let totalNum = 0;
cart.forEach((v) => {
if (v.checked) {
totalPrice += v.num * v.goods_price;
totalNum += v.num;
} else {
allchecked = false;
}
});
//判断数组是否为空
allchecked = cart.length != 0 ? allchecked : false;
this.setData({
cart,
allchecked,
totalPrice,
totalNum,
});
wx.setStorageSync("cart", cart);
},
商品数量的加减:在加号和减号给其绑定一个单击事件,表示数量是加一还是减一,根据按钮绑定的operation值决定,并且当数量为1时,单击减号要淡出提示:问用户是否决定删除。将修改后的值cart缓存,壶盖原数组。
handleItemNumEdit(e) {
const { operation, id } = e.currentTarget.dataset;
//console.log(operation,id)
//获取购物车数组
let { cart } = this.data;
//找到需要修改的索引
const index = cart.findIndex((v) => v.goods_id === id);
//修改数量
if (cart[index].num === 1 && operation === -1) {
//跳出弹窗提示
wx.showModal({
title: "提示",
content: "是否要删除",
success: (result) => {
if (result.confirm) {
cart.splice(index, 1); //表示删除这一条数据
this.setCart(cart);
} else if (result.cancel) {
console.log("取消删除");
}
},
});
} else {
cart[index].num += operation;
//设置回缓存和data中
this.setCart(cart);
}
},
是否选中,在checked属性中,单击一次后表示选中,再次单击后取消,就类似于原先的收藏功能。切只有被选中了的商品才会进行计算到总价格当中。
handleItemChange(e) {
//获取id
const goods_id = e.currentTarget.dataset.id;
//console.log(goods_id)
//获取购物车数组
let { cart } = this.data;
let index = cart.findIndex((v) => v.goods_id === goods_id);
//取反 加上!非。
cart[index].checked = !cart[index].checked;
this.setCart(cart);
},
商品的全选,在下方单击全选按钮后,对商品的所有数据的checked值改为true:即全选。
handleItemAllchange(e) {
let { cart, allchecked } = this.data;
//修改选中状态
allchecked = !allchecked;
//循环修改cart数组当中的选中状态
cart.forEach((v) => (v.checked = allchecked));
//修改后的值进行填充
this.setCart(cart);
},
最后商品结算:单击结算按钮后需要判断是否有收货地址,以及是否有商品进行购买:条件都满足后将进行跳转到结算界面:使用wx.navigateTo进行跳转
//商品结算
handlePay(e) {
//判断收货地址
const { address, totalNum } = this.data;
if (address.userName === "") {
wx.showToast({
title: "还未选择收货地址",
icon: "none",
success: (result) => {},
fail: () => {},
complete: () => {},
});
return;
}
//判断是否有选购商品
if (totalNum === 0) {
wx.showToast({
title: "还未选购商品",
icon: "none",
success: (result) => {},
fail: () => {},
complete: () => {},
});
return;
}
//执行正常购买商品的逻辑,即跳转页面
wx.navigateTo({
url: "/pages/pay/index",
});
},
在storage当中可以查看到这个缓存的对象:如下图所示:
以及缓存当中的cart,点开cart可以看到是否选中的属性checked:如下图:
与此同时在appdata里面可以看到页面的对应的属性值:如下,共有5条商品 cate数组的大小为5 是否全部选中的allchecked属性值为true 、address地址信息也存在、totalPrice总价格,totalNum总条数
感谢你的阅览,文章持续更新中…
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)