本篇文章详解Cart页面滑动、icon触发事件
涉及到class三元表达式、bindtouchstart、bindtouchmove、自定义事件
滑动详解
滑动效果的实现 主要是:transition动画 + margin-left左外边距
默认的,我们让content盒子初始外边距为-90rpx
再利用transition动画将盒子向右移动90rpx
让content盒子视觉上回到中心
.content{
margin-left:-90px;
transform:translateX(90px);
transition:all 0.4s;
}
同样的,我们设置remove
.remove{
transform:translateX(90px);
transition:all 0.4s;
}
基础滑动实现
.touch-move.content .touch-move.remove{
transform:translateX(0px);
}
触摸事件
给元素绑定触摸事件
bindtouchstart=“touchstart”
bindtouchmove=“touchmove”
isTouchMove:false;//控制list移动
<view class="list {{isTouchMove?'touch-move':''}}"
bindtouchstart="touchstart"
bindtouchmove="touchmove" >
class三元表达式
class=“list {{isTouchMove?‘touch-move’:‘’}}
当isTouchMove=true时 =>有"touch-move”(触发动画0px)
当isTouchMove=false时 =>" "(空)
获取手指触碰页面的X轴参数
touchstart:function(e){
this.setData({
startx:e.changeTouches[0].clientX
})
}
获取手指移动的X轴参数
touchmove:function(e){
var list=this.data.list;
var index=e.currentTarget.dataset.index;
var endx=e.changedTouches[0].clientX;
var start=this.data.startx;
if(endx>startx){
list[index].isTouchMove=true;//左滑
}else{
list[index].isTouchMove=false;//右滑
}
this.setData({
list:list
})
}
list-icon选中
利用selected控制list-icon状态
<view class="circle">
<icon bindtap="selectedList" data-index="{{index}}"
wx:if='{{item.selected}}' type='success' size='23'>
<icon bindtap="selectedList" data-index="{{index}}"
wx:else type='circle' size='23'>
selectedList:function(e){
var index=e.currentTarget.dataset.index;
var list=this.data.list;
list[index].selected=!list[index].selected;
var num=this.data.num;
if(list[index].selected){
num++;
}else{
num--;
}
if(num>0){
this.setData({
isShow:true;
})
}else{
this.setData({
isShow:false;
}
if(num==list.length){
this.setData({
selectedAll:true;
})
}else{
selectedAll:false;
}
this.setData({
list:list,
num:num
})
}
icon全选
利用selectedAll控制“全选”icon状态
selectAll:function(){
var selectedAllStatus=!this.data.selectedAll;
var list=this.data.list;
var num=this.data.num;
var isShow=this.data.isShow;
for(var i=0;i<list.length;i++){
//获取当前“全选”icon状态
list[i].selected=selectedAllStatus
}
//当全选icon为TRUE时,表明全选
if(selectedAllStatus){
num=list.length;
isShow=true;//“结算”高亮
}else{
//当全选icon为FALSE时,表明不全选
num=0;
isShow=false;//取消“结算”高亮
}
//更新数据
this.setData({
selectedAll:selectedAllStatus,
list:list,
num:num,
isShow:isShow
})
this.getTotalPrice();
}
价格高亮&计算
利用isShow控制“结算”高亮
<view class="heji">合计<text>{{totalPrice}}</text></view>
<view class="jiesuan {{isShow?'active:''}}">结算({{totalPrice}})</view>
.active{
background:green;
}
goTotalPrice:function(){
var list=this.data.list;
var totalPrice=0;
for(var i=0;i<list.length;i++){
if(list[i].selected){
totalPrice+=list[i].price*list[i].num
}
}
this.setData({
totalPrice:totalPrice.toFixed(2)//末尾保留两位小数
})
}
删除事件
<view class="remove" bindtap="delete" data-id="{{item.id}}">删除</view>
点击触发delete事件 获取当前元素位置
请求后台的删除接口数据 => 传递需要的id
再次请求购物车数据 =>更新
delete:function(e){
var id=e.currentTarget.dataset.id;
wx.request({
url:'http://iwenwiki.com:3002/api/cart/delete',
data:{
id:id
}
success:res=>{
if(res.data.status==200){
wx.showToast({
title:"删除成功",
icon:none
})
this.getShopData();
}
}
})
}
+商品
<view class="add" bindtap="addNum" data-num="{{item.num}}" data-index="{{index}}">+</view>
addNum:function(e){
var list=this.data.list;
var index=e.currentTarget.dataset.index;
var num=e.currentTarget.dataset.num;
num++;
list[index].num=num;
this.setData({
list:list
})
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/update',
data:{
id:list[index].id,
num:num
},
success:res=>{
if(res.data.success){
wx.showToast({
title: '加入购物车成功',
icon:'none'
})
}
}
})
},
-商品
<view class="reduce" bindtap="removeNum" data-num="{{item.num}}" data-index="{{index}}" data-id="{{item.id}}">-</view>
removeNum:function(e){
var list=this.data.list;
var index=e.currentTarget.dataset.index;
var num=e.currentTarget.dataset.num;
num--;
if(num>0){
list[index].num=num;
this.setData({
list:list
})
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/update',
data:{
id:list[index].id,
num:num
},
success:res=>{
if(res.data.success){
wx.showToast({
title: '加入购物车成功',
icon:'none'
})
}
}
})
}
if(num==0){
var id=e.currentTarget.dataset.id;
wx.request({
url:'http://iwenwiki.com:3002/api/cart/delete',
data:{
id:id
},
success:res=>{
if(res.data.status==200){
wx.showToast({
title:"删除成功",
icon:'none'
})
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/list',
success:res=>{
if(res.data.status==200){
this.setData({
list:res.data.data.result
})
}else{
console.log("获取数据失败")
}
}
})
}
}
})
}
},
shopDetail页面优化
加入购物车
<view class="shop" bindtap="add" >加入购物车</view>
add:function(e){
var obj=this.data.obj;
console.log(obj)
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/add',
data:{
name:obj.name,
pic:obj.pic,
num:1,
info:obj.description,
price:obj.price
},
success:res=>{
if(res.data.status==200){
wx.showToast({
title: '成功加入购物车',
icon:'none'
})
}else{
console.log("添加失败");
}
}
})
},
图片跳购物车
<view class="img" bindtap="shopping"><image src="../../images/tab3.png"></image></view>
shopping:function(){
wx.switchTab({
url: '../shop/shop',
})
},
【成果展示】
shop.wxml
<view wx:for="{{list}}" wx:key="index"
class="list {{item.isTouchMove?'touch-move':''}}"
data-index="{{index}}"
bindtouchstart="touchstart"
bindtouchmove="touchmove">
<view class="content">
<view class="circle">
<icon bindtap="selectedList" data-index="{{index}}"
wx:if='{{item.selected}}' type='success' size='23'>
</icon>
<icon bindtap="selectedList" data-index="{{index}}"
wx:else type='circle' size='23'>
</icon>
</view>
<view class="img">
<image src="{{item.pic}}"></image>
</view>
<view class="wrapper">
<view class="th">{{item.name}}</view>
<view class="desc">{{item.info}}</view>
<view class="info">
<view class="price">¥{{item.price}}</view>
<view class="update">
<view class="reduce" bindtap="removeNum" data-num="{{item.num}}" data-index="{{index}}" data-id="{{item.id}}">-</view>
<view class="num">{{item.num}}</view>
<view class="add" bindtap="addNum" data-num="{{item.num}}" data-index="{{index}}">+</view>
</view>
</view>
</view>
</view>
<view class="remove" bindtap="delete" data-id="{{item.id}}">删除</view>
</view>
<!-- 底部结算栏 -->
<view class="height"></view>
<view class="bottom">
<view class="checkboxAll">
<view class="icon">
<icon wx:if="{{selectedAll}}" data-id="{{index}}" bindtap="selectedAll" type="success" size="23"></icon>
<icon wx:else type="circle" bindtap="selectedAll" size="23"></icon>
</view>
<view class="text">全选</view>
</view>
<view class="heji">合计<text>{{totalPrice}}</text></view>
<view class="jiesuan {{isShow?'active':''}}">结算({{totalPrice}})</view>
</view>
shop.js
Page({
data: {
list:[],
starx:0,
stary:0,
isTouchMove:false,
selected:false,
selectedAll:false,
isShow:false,
price:0,
totalPrice:0,
num:0,
},
getshopData:function(){
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/list',
success:res=>{
if(res.data.status==200){
this.setData({
list:res.data.data.result
})
}else{
console.log("获取数据失败")
}
}
})
},
touchstart:function(e){
this.setData({
starx:e.changedTouches[0].clientX
})
},
touchmove:function(e){
var list=this.data.list;
var index=e.currentTarget.dataset.index;
var endx=e.changedTouches[0].clientX;
var startx=this.data.startx;
if(endx>starx){
list[index].isTouchMove=true
}else{
list[index].isTouchMove=false
}
this.setData({
list:list
})
},
goTotalPrice:function(){
var list=this.data.list;
var totalPrice=0;
for(var i=0;i<list.length;i++){
if(list[i].selected){
totalPrice+=list[i].price*list[i].num
}
}
this.setData({
totalPrice:totalPrice.toFixed(2)//末尾保留两位小数
})
},
selectedList:function(e){
var index=e.currentTarget.dataset.index;
var list=this.data.list;
list[index].selected=!list[index].selected;
var num=this.data.num;
if(list[index].selected){
num++;
}else{
num--;
}
if(num>0){
this.setData({
isShow:true
})
}else{
this.setData({
selectedAll:false,
isShow:false
})
}
if(num==list.length){
this.setData({
selectedAll:true
})
}
else{
selectedAll:false
}
this.setData
({
list:list,
num:num,
})
this.goTotalPrice();
},
selectedAll:function(){
var selectedAllStatus=!this.data.selectedAll;
var list=this.data.list;
var num=this.data.num;
var isShow=this.data.isShow;
for(var i=0;i<list.length;i++){
//获取当前“全选”icon状态
list[i].selected=selectedAllStatus;
}
console.log(selectedAllStatus)
//当全选icon为TRUE时,表明全选
if(selectedAllStatus){
num=list.length;
isShow=true;//“结算”高亮
this.goTotalPrice();
}else{
//当全选icon为FALSE时,表明不全选
num=0;
isShow=false;//取消“结算”高亮
var totalPrice=0;
}
//更新数据
this.setData({
selectedAll:selectedAllStatus,
list:list,
num:num,
isShow:isShow,
totalPrice:totalPrice,
})
},
delete:function(e){
var id=e.currentTarget.dataset.id;
wx.request({
url:'http://iwenwiki.com:3002/api/cart/delete',
data:{
id:id
},
success:res=>{
if(res.data.status==200){
wx.showToast({
title:"删除成功",
icon:none
})
this.getShopData();
}
}
})
},
removeNum:function(e){
var list=this.data.list;
var index=e.currentTarget.dataset.index;
var num=e.currentTarget.dataset.num;
num--;
if(num>0){
list[index].num=num;
this.setData({
list:list
})
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/update',
data:{
id:list[index].id,
num:num
},
success:res=>{
if(res.data.success){
wx.showToast({
title: '加入购物车成功',
icon:'none'
})
}
}
})
}
if(num==0){
var id=e.currentTarget.dataset.id;
wx.request({
url:'http://iwenwiki.com:3002/api/cart/delete',
data:{
id:id
},
success:res=>{
if(res.data.status==200){
wx.showToast({
title:"删除成功",
icon:'none'
})
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/list',
success:res=>{
if(res.data.status==200){
this.setData({
list:res.data.data.result
})
}else{
console.log("获取数据失败")
}
}
})
}
}
})
}
},
addNum:function(e){
var list=this.data.list;
var index=e.currentTarget.dataset.index;
var num=e.currentTarget.dataset.num;
num++;
list[index].num=num;
this.setData({
list:list
})
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/update',
data:{
id:list[index].id,
num:num
},
success:res=>{
if(res.data.success){
wx.showToast({
title: '加入购物车成功',
icon:'none'
})
}
}
})
},
onLoad(options){
},
onShow() {
this.getshopData()
},
})
shop.wxss
/* pages/shop/shop.wxss */
page{
background: #f5f5f5;
}
.list{
display: flex;
background-color: #fff;
justify-content: space-between;
}
.content{
flex: 1;
width: 100%;
display: flex;
padding: 20rpx;
background: #fff;
margin-left: -90px;
transform: translateX(90px);
transition: all 0.4s;
}
.remove{
width: 90px;
background: red;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
height: 200rpx;
transform: translateX(90px);
transition: all 0.4s;
}
.touch-move.content,.touch-move.remove{
transform: translateX(0px);
}
.img image{
width: 184rpx;
height: 184rpx;
padding-left: 20rpx;
padding-right: 20rpx;
}
.wrapper{
height: 184rpx;
position: relative;
}
.desc{
color: #666;
font-size: 26rpx;
margin-top: 10rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.th{
font-size: 28rpx;
}
.info{
position: absolute;
bottom: 0;
left: 0;
font-size: 26rpx;
display: flex;
}
.info .price{
font-size: 30rpx;
color: red;
position: fixed;
bottom:10rpx;
padding-right: 40rpx;
}
.update{
bottom: 0%;
display: flex;
padding-right: 20rpx;
text-align: center;
position: fixed;
right: 10rpx;
padding-bottom: 5rpx;
}
.update .reduce{
width: 40rpx;
height: 40rpx;
border: 1rpx solid #999;
font-size: 30rpx;
}
.update .num{
padding-left: 20rpx;
padding-right: 20rpx;
}
.update .add{
width: 40rpx;
height: 40rpx;
color: #fff;
background: #333;
border: 1rpx solid #999;
}
.height{
height: 160rpx;
}
.bottom{
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
background: #fff;
}
.checkboxAll{
flex:1;
display: flex;
align-items: center;
padding-left: 20rpx;
}
.text{
padding-left: 5rpx;
padding-bottom:10rpx;
}
.heji{
padding:20rpx;
}
.jiesuan{
padding:20rpx;
background: #999;
color: #fff;
}
.active{
background-color: green;
}
shopDetail.wxml
<!--pages/shopDetail/shopDetail.wxml-->
<view class="name">{{obj.name}}</view>
<view class="container">
<view class="product">产品信息介绍</view>
<image src="{{obj.pic}}"></image>
<view class="desc">{{obj.details}}</view>
</view>
<!-- <view class="name">产品名称</view>
<view class="container">
<view class="product">商品</view>
<image src="../../images/banner.jpg"></image>
<view class="desc">信息介绍</view>
</view> -->
<view class="bottom">
<view class="img" bindtap="shopping"><image src="../../images/tab3.png"></image></view>
<view class="shop" bindtap="add" >加入购物车</view>
<view class="buyNow">直接购买</view>
</view>
shopDetail.js
// pages/shopDetail/shopDetail.js
Page({
data:{
obj:{}
},
shopping:function(){
wx.switchTab({
url: '../shop/shop',
})
},
add:function(e){
var obj=this.data.obj;
console.log(obj)
wx.request({
url: 'http://iwenwiki.com:3002/api/cart/add',
data:{
name:obj.name,
pic:obj.pic,
num:1,
info:obj.description,
price:obj.price
},
success:res=>{
if(res.data.status==200){
wx.showToast({
title: '成功加入购物车',
icon:'none'
})
}else{
console.log("添加失败");
}
}
})
},
onLoad(options) {
console.log(options)
wx.request({
url: 'http://iwenwiki.com:3002/api/foods/list/detail',
data:{
id:options.id
},
success:(res)=>{
console.log(res.data.data)
if(res.data.status==200){
this.setData({
obj:res.data.data[0]
})
}
}
})
},
})
遇到一个bug
在shopDetail页面点击两次以上“加入购物车”后
shop页面同样的商品并没有按数量累加,而是单数量平铺增加
这个问题要如何解决,求解…
总结
以上就是Cart页面的优化内容
通过做本篇的内容准备,我对自定义方法和相关的数据调用有了更深的理解与巩固,在“滑动”内容的学习中,也了解到HTML结合css更多的玩法和可能性,不得不感慨制作者的脑洞~转来转去也是有点子头疼的哈哈。
谢谢你今天看到这里,我们明天见~