前言
七夕刚刚过去,想必各位为了心爱的那个ta💕在得物上花了不少钱吧。正好最近暑假正在学习微信小程序开发,与两个志同道合的小伙伴共同开发了一个仿得物APP微信小程序。这篇文章就给大家主要分享一些JS逻辑和页面设计,以及一些心得体会遇到的bug。希望能够帮到一些小程序初学者。
项目开发准备
项目目标
- 整个项目是基于小程序云开发的全栈项目,使用了云数据库进行数据操作。友军😘负责了购买首页、商品详情页、搜索页、品牌分类页的编写,想了解更多的可以点击传送门。而我主要负责的是登录功能和"我的"页面编写以及购买功能的实现。
功能展示以及代码分析
|
|
|
登录功能实现和页面样式
页面展示
|
|
|
结构代码
<view class="login__hd">
<view class="login-1-1">
<view bindtap="return">
<image src="https://cdn.poizon.com/node-common/YmFja0AzeDE1OTM3NTU3NDQ4NDk=.png" class="login-1-1-left"></image>
</view>
<view class="login-1-1-auto"></view>
<view bindtap="more">
<image src="https://cdn.poizon.com/node-common/aG9tZUAzeDE1OTM3NTU3MDU5MjM=.png" class="login-1-1-right"></image>
</view>
</view>
<view class="login__hd_title">
<h1>登录</h1>
</view>
</view>
<view class="login__bd">
<view class="login__bd_pic">
<image class="image-1"></image>
<image class="image-2"></image>
</view>
<view class="login__bd_main">
<button class="user-btn1 " openType="getUserInfo" bindgetuserinfo="getUserInfo" >微信登录</button>
<button class="user-btn3 {{isAgreed?'active1': ''}}" bindtap='showtips' >微信登录</button>
<button class="user-btn2">手机号登录/注册</button>
</view>
<view class="login__bd_info">
<view class="check_btn {{activeIndex == 1?'active2': ''}}" bindtap="agree"></view>
<view class="check_txt">
<h1>已阅读并同意<h2 bindtap="show_detail">用户协议、隐私政策、买家须知</h2>
</h1>
</view>
</view>
</view>
当我们在没有勾选用户协议的时候是不能微信登录的,所有我在这里使用了两个样式一样的button,其中一个用三元运算符绑定了一个新的类名{{isAgreed?'active1': ''}}并且在勾选处以同样的原理绑定了{{activeIndex == 1?'active2': ''}}在勾选标签上。用以下JS逻辑即可实现勾选协议后授权登录
JS逻辑代码
Page({
data: {
activeIndex: 0,
isLogged: false,
isAgreed: false
},
showtips() {
if (!this.data.isAgreed) {
wx.showToast({
title: '请先勾选协议',
icon: 'none'
})
}
},
agree() {
if (this.data.activeIndex == 0) {
this.setData({
activeIndex: 1,
isAgreed: true
})
} else {
this.setData({
activeIndex: 0,
isAgreed: false
})
}
console.log(this.data.isAgreed);
},
getUserInfo(e) {
// console.log(e);
// console.log(this.data.isAgreed);
if (e.detail.userInfo == null) {
wx.switchTab({
url: '../login/login',
})
} else {
this.setData({
isLogged: true
})
console.log(this.data.isLogged);
if (this.data.isLogged) {
wx.switchTab({
url: '../buy_page/page/buy/buy'
})
}
}
},
show_detail() {
wx.navigateTo({
url: '../login_detail/login_detail',
})
},
})
支付页面样式
页面展示
|
|
|
结构展示
<van-cell title="收货人: 刘小瞳" icon="location-o" value="187****1206" size="large" label="北京字节跳动科技有限公司" is-link />
<van-card price="{{goods.price}}" desc="L 数量x1" title="{{goods.title}}" thumb="{{goods.pic}}" />
<van-cell-group>
<van-cell title="顺丰速运" value="¥18" />
<van-cell value-class="cell2" title="优惠卷" value="-¥15" border="{{ false }}" is-link />
</van-cell-group>
<view class="check_txt">
<h1>1、若卖家未在36小时内发货导致交易关闭且平台未为您匹配到新订单,您将获得28.00元现金及总计人民币170元的满减优惠券补偿。</h1>
<h1>2、每件交易商品均由平台针对实物进行鉴别,鉴于商品价格波动性,同时每个款式每个尺码的商品出售时仅有—件等情况,故不支持退还差价。</h1>
<h1>3、企业商家ID:B21031855774654,因商品拆封鉴别,不支持七天无理由退货。</h1>
<h1>提交订单即表示同意买家须知<h2 bindtap="show_detail">买家须知</h2>
</h1>
</view>
<view class="pay_foot">
<view class="payMoney">
<h1>实付款:¥<h2>{{newPrice}}</h2></h1>
<!-- 存ID -->
<van-button bind:click="pay" data-id="{{goods.id}}" data-title="{{goods.title}}"data-price="{{goods.price}}"data-pic="{{goods.pic}}" class="b1" type="primary" size="small" color="#01B8B9" square="true" custom-style="width: 200rpx">提交订单</van-button>
</view>
</view>
支付页面中地址采用van-cell。属性中可以设置title、icon、lable等信息
商品信息进行了数据绑定,上一个页面点击时会将商品id传过来
JS逻辑代码
gotoPay(e) {
wx.navigateTo({
url: '/pages/buy_page/page/pay/pay?id='+this.data.id,
})
}
然后支付界面连接云数据库,通过传来的id查询商品的信息并setData
const db = wx.cloud.database()
const dewuCollection = db.collection('dewu')
data: {
goods: [],
newPrice: 0,
id: ''
},
async onLoad(e) {
console.log(e);
let id = e.id;
console.log(id);
await dewuCollection
.doc(id)
.get()
.then(res => {
// console.log(res.data);
let Homedata = res.data
this.setData({
goods: Homedata,
id: id
})
})
},
})
云数据库文件可自行编写成csv或者json格式导入,云数据库格式可以去这里取
我的页面样式
页面展示
结构代码
<view class="weui-cells weui-cells_after-title my_tools">
<!-- 购买栏 -->
<block wx:for="{{buy}}" wx:key="index">
<navigator style="border-bottom: none" url="{{item.url}}">
<view class="weui-cell weui-cell_access weui-cell_example ">
<view class="weui-cell__hd">
<image class="icon-img" src="{{item.icon}}"></image>
</view>
<view class="weui-cell__bd">{{item.title}}<p>全部订单 2</p>
</view>
<view class="weui-cell__ft"></view>
</view>
</navigator>
</block>
<!-- 其他栏 -->
<block wx:for="{{collect}}" wx:key="index">
<navigator url="{{item.url}}">
<view class="weui-cell weui-cell_access weui-cell_example ">
<view class="weui-cell__hd">
<image class="icon-img" src="{{item.icon}}"></image>
</view>
<view class="weui-cell__bd">{{item.title}}</view>
<view class="weui-cell__ft"></view>
</view>
</navigator>
</block>
</view>
购买功能实现(重头戏)
页面展示
|
|
|
页面的设计比较简单,用vant组件都能够实现,头部的van-tab用sticky吸顶,底部的结算栏用position:fixed滞留在底部
结构代码
<van-tabs color='black' sticky active="a">
<van-tab title="待付款" name="a">
<view class="buy__info page1">
<view class="buy__info_goods" wx:for="{{goods}}" wx:key="index">
<!-- 选择 -->
<view class='icon'>
<icon wx:if="{{item.selected}}" type="success" color="#00BABA" size="20" bindtap="selectedCart"
data-index="{{index}}" />
<icon wx:else type="circle" bindtap="selectedCart" size="20" data-index="{{index}}" />
</view>
<!-- 商品 -->
<van-card price="{{item.price}}" desc="数量 x {{item.value}}" title="{{item.title}}" thumb="{{item.pic}}" />
<!-- 删除 -->
<view class='right'>
<image
src='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic175.nipic.com%2Ffile%2F20180804%2F24144945_114304501035_2.jpg&refer=http%3A%2F%2Fpic175.nipic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1631876010&t=e1da2162c6dc0c2bd878cad1a269e24d'
bindtap='delete' data-index="{{index}}"></image>
</view>
<!-- 结算 -->
<view class="cart-bottom">
<icon wx:if="{{CheckAll}}" class="cart-icon" type="success" color="#00BABA" size="20" bindtap="select"
data-index="{{index}}" />
<icon wx:else type="circle" class="cart-icon" size="20" bindtap="select" data-index="{{index}}" />
<text class='checkAll'>全选</text>
<view class='cart-pay'>
<text class='cart_pay' bindtap="cleanAll" data-index="{{index}}" data-id="{{item.id}}">全部结算</text>
</view>
<view class='cart-sum'>
<text class='cart_sum'>
<text class='sum_text'>合计:</text>
<text class='sum_color'>¥{{total}}元</text>
</text>
</view>
</view>
</view>
</view>
</van-tab>
<van-tab title="待发货">
<view class="buy__info page2">
<p>这里还没有内容</p>
</view>
</van-tab>
<van-tab title="待收货">
<view class="buy__info page3">
<p>这里还没有内容</p>
</view>
</van-tab>
<van-tab title="全部订单">
<view class="buy__info page4">
<view class="buy__info_goods" wx:for="{{goods}}" wx:key="index">
<view class="buy__info_goods_hd">交易成功</view>
<van-card price="{{item.price}}" desc="数量 x {{item.value}}" title="{{item.title}}" thumb="{{item.pic}}" />
</view>
</view>
</van-tab>
</van-tabs>
整个购物车操作实现了商品购买数量计算,价格计算,勾选绑定以及清空记录。那么该如何在不同的界面获得这些复杂的数据呢👀?
我们都知道不同页面获取数据在小程序中无非这几种方法:
- url带参传递数据
- 全局变量传递数据
- 本地缓存传递数据
而想要实现这么多功能,这里使用了
wx.setStorageSync(string key, Object|string data)和url传参混合使用
JS逻辑代码
提交订单按钮
pay(e) {
let goods = wx.getStorageSync("goods") || []
let exist = goods.find((el) => {
console.log(e);
return el.id == this.data.id
})
// console.log(e);
//如果购物车里面有该商品那么他的数量每次加一
if (exist) {
exist.value = parseInt(exist.value) + 1
} else {
goods.push({
id: this.data.id,
title: e.target.dataset.title,
pic: e.target.dataset.pic,
price: e.target.dataset.price,
value: 1,
selected: true
})
}
// console.log(goods);
//更新缓存数据
wx.setStorageSync("goods", goods)
wx.showLoading({
title: '提交订单中',
})
setTimeout(function () {
wx.hideLoading()
wx.showToast({
title: '提交成功',
icon: 'success',
duration: 1000
})
}, 1000)
setTimeout(function () {
wx.switchTab({
url: '../buy/buy',
})
}, 1500)
},
点击提交订单按钮,wx.getStorageSync("goods")创建key值,并且判断在购物车中是否存在该商品,如果存在则数量+1,不存在即goods.push, 并更新缓存数据。
购物车基本业务逻辑
const db = wx.cloud.database()
const dewuCollection = db.collection('dewu')
Page({
data: {
goods: [],
total: 0,
CheckAll: false
},
onLoad() {
wx.setNavigationBarTitle({
title: '我的购买'
})
},
onShow() {
let goods = wx.getStorageSync("goods")
this.setData({
cartList: false,
goods: goods
})
console.log(goods);
}
})
在这里我们要注意this.setData应该放在onShow()函数中,因为我们要的是每次进入此页面就加载storage中的数据,所以不放在onLoad中。
选择所有商品
// 选择所有商品
select(e) {
let CheckAll = this.data.CheckAll;
CheckAll = !CheckAll
let goods = this.data.goods
for (let i = 0; i < goods.length; i++) {
goods[i].selected = CheckAll
}
this.setData({
goods: goods,
CheckAll: CheckAll
})
this.getTotal()
}
选择指定商品
// 选择商品
selectedCart(e) {
var goods = this.data.goods //获取购物车列表
var index = e.currentTarget.dataset.index; //获取当前点击事件的下标索引
var selected = goods[index].selected; //获取购物车里面的value值
//取反
goods[index].selected = !selected;
this.setData({
goods: goods
})
this.getTotal();
wx.setStorageSync("goods", goods)
}
我们可以用 e.currentTarget.dataset.index获取当前点击事件的下标索引,然后goods[index].selected取得购物车里面的value值
删除商品
//删除
delete(e) {
let goods = this.data.goods //获取购物车列表
let index = e.currentTarget.dataset.index //获取当前点击事件的下标索引
goods.splice(index, 1)
this.setData({
goods: goods
});
if (goods.length) {
this.setData({
cartList: false
});
}
this.getTotal()
wx.setStorageSync("goods", goods)
}
同理获取下标后也可以选择goods.splice(index, 1)删除商品
计算总价格
//合计
getTotal() {
let sum = 0
for (let i = 0; i < this.data.goods.length; i++) {
if (this.data.goods[i].selected) {
sum += this.data.goods[i].value * this.data.goods[i].price
}
}
//更新数据
this.setData({
total: sum
})
}
最后最重要的计算商品价格来了,以后再也不怕给女朋友买礼物超额了😘
给大家的建议
各位小码农们自己在写项目的时候有bug就多打断点多console.log()看看自己哪里出了问题,如果没有报错但是数据有没拿到,那就仔细检查一些直接调用时有没有出现拼写错误。在处理复杂业务逻辑时不妨先想清楚,再下手也不迟。设计页面的时候多看看多学学微信小程序开发文档和Vant Vant Weapp。
本项目源码
结语
经历过合作开发的程序猿应该都有着同感,项目开发应该是件高兴的事,可是问题又来了,以前只是个人开发项目啊,文档写写,图画画,自己能看懂就得了,最主要是写代码,把软件设计完成就可以万事大吉了。但通过现在合作开发,不是你个人的项目,大家共同努力才可以写出一个好的项目。非常感谢在我写项目过程中帮助过我的老师和同学。如果你喜欢我的这篇文章或者看到这里对你有些许帮助,不妨点个赞吧😺!