微信小程序——商城篇
前言
随着wepy和mpvue的出现及流行,开发小程序变的越来越便捷和强大,作为基佬社区的一份子,我们都需要把自己遇到的问题以及如何解决的方式相互分享,这样才能帮助到更多的朋(ji)友(lao)。如有写的不足的地方,请各位提出宝贵的建议哈。
简单介绍微信小程序
众所周知,小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心是否安装太多应用的问题,因此它的开发程度也较为简单。
- 开发技术: WXML(HTML5)、WXSS(CSS)、JavaScript
- 开发工具: vscode(可以使用下列几种框架来进行开发),微信开发者工具
- 开发思路: MVVM,简单来说,这就是一门把前端开发者从操作DOM的繁琐步骤中解脱出来,让数据自动更新界面的技术。
- 开发流程: 这个大家可以看官方的文档,下载安装开发工具以后使用appid就可以进行开发了。小程序简易教程
- 开发单位: rpx,pt,rem等,具体在这里就不介绍了
- 开发框架: 这里介绍几种小程序的框架,有weui,wepy,mpvue等,有兴趣的同学可以自主去了解一下
作为一枚前端战场的工兵,自然少不了踩雷,而且不用框架组件式开发来手动切页面有点小心酸~~在这里我分享几个自己用原生微信小程序开发遇到的坑,
1. 微信小程序之wx.showModal
给confirm/cancel属性设置字体颜色的时候会有一个小坑, mode代码:
<view bindtap="test"> <text>测试</text> </view> js代码: test(e) { wx.showModal({ content: '测试', cancelColor: 'red', confirmColor: 'rgb(255,0,0)' }) }
这样的代码在模拟器上显示一切正常,两个按钮也的确变颜色了。可是在手机上一看,傻眼了
原来这2个按钮的颜色值只支持十六进制的。
js代码: test(e) { wx.showModal({ content: '测试', cancelColor: '#FF0000', confirmColor: '#FF0000' }) }
这样两个按钮就在手机上也能出来了,并且颜色得到了改变。
2. 微信小程序之navigator跳转
在进入商品详情页以后,点击左下角的home图标原应该跳转到首页,但是一直点也不跳,而且也不报错。
wxml代码:
<navigator hover-class="none" url="/pages/index/index"> <image src="/libs/images/home.png"></image> </navigator>
仔细查看了路径无误和字母没打错以后,这个问题卡了我半个小时以后终于发现这里有一个不够细心就会踩的坑,
常用wx.switchTab 接口的同学可能没碰到过这种情况。navigator组件里有一个属性是open-type,默认值是navigate,对应 wx.navigateTo 或 wx.navigateToMiniProgram 的功能。
聪明的同学应该已经看出问题所在了,是的,这里要跳转的首页就是一个tabBar页面,按照默认的跳转方式是不能实现的。
解决方法:
<navigator hover-class="none" open-type="switchTab" url="/pages/index/index"> <image src="/libs/images/home.png"></image> </navigator>
加一个open-type="switchTab" 或者绑定一个点击事件用wx.switchTab接口来实现。
3. 微信小程序之scroll-x
小程序的scroll-view组件还有一个横向滑动的属性:scroll-x
但是对于类似我这样的新手来说,设置scroll-x的时候,会把要滑动的内容给挤成多行。
在这里直接给出一个解决方法:
- 给scroll-x设置一个宽度,并设置white-space: nowrap属性 //内容不换行
- 把内容view盒子设置为行内块元素 display: inline-block
即可解决横向滑动内容不在一行的问题,在下面我简单贴一下项目中我这块内容的代码。
4. swiper组件和input组件一起用
问题:如果把一个input组件绝对定位到swiper组件上,swiper还是会覆盖input组件,而input组件内的placeholder属性则会透出来,虽然不影响input的功能,但是会影响到input属性的显示效果,也就是影响了视觉上的效果。
模拟器上的效果:
手机上的效果:
代码:
<view class="hd"> <input class="input" placeholder="搜索商品,共9803款好物" bindtap="entrySearch" disabled /> <swiper class="receive"> <swiper-item > <navigator url="/pages/index/receive/receive" hover-class="none"> <image class="receive_img" src="/libs/images/index.jpg" mode="aspectFill"></image> </navigator> </swiper-item> </swiper> </view>
.input { position: absolute; left: 30rpx; top: 10rpx; box-sizing: border-box; width: 690rpx; height: 56rpx; border-radius: 45rpx; border: 1rpx solid #000; //证明自己的猜测 background-color: #fff; box-shadow: 0 0 1rpx #ccc; text-indent: 185rpx; font-size: 0.8rem; } .receive { height: 380rpx; } .receive_img { width: 750rpx; height: 380rpx; }
我们可以看到模拟器上显示正常,但是在手机上就成了方型的框,我开始排查问题,我猜测是被覆盖了?于是我就添加了border: 1rpx solid #000;这行代码,进行刷新以后发现黑线边框出来了一下马上就消失了,果然!用了绝对定位都被覆盖了。
解决方法: 给input组件加个z-index:2 。 当然,建议给input组件再套一个view盒子。
代码:
<view class="hd"> <view class="inputSearch"> <input class="input" placeholder="搜索商品,共9803款好物" bindtap="entrySearch" disabled /> </view> <swiper class="receive"> <swiper-item > <navigator url="/pages/index/receive/receive" hover-class="none"> <image class="receive_img" src="/libs/images/index.jpg" mode="aspectFill"></image> </navigator> </swiper-item> </swiper> </view> .inputSearch { position: absolute; left: 30rpx; top: 10rpx; box-sizing: border-box; width: 690rpx; height: 56rpx; border-radius: 45rpx; z-index: 2; background-color: #fff; box-shadow: 0 0 1rpx #ccc; } .input { text-indent: 185rpx; font-size: 0.8rem; } .receive { height: 380rpx; } .receive_img { width: 750rpx; height: 380rpx; }
5. 微信小程序之scroll-into-view
我在这里就一种能实现的方法,假数据可以通过easymock造一下再wx.request引入,也可以直接放到一个js文件里import引入,这里不详细讲解。
一开始我以为是用两个scroll-view来做,通过scroll-into-view这个属性来实现左右关联进行滚动的效果
代码:
<view class="main"> <scroll-view class="menu-left" scroll-y scroll-with-animation="{{true}}"> <view class="cate-list {{curIndex==index?'on':''}}" wx:for="{{menu}}" wx:key="{{item.id}}" data-id="{{item.id}}" data-index="{{index}}" bindtap="switchCategory"> <text>{{item.name}}</text> </view> </scroll-view> <scroll-view scroll-y class="menu-right" scroll-into-view="{{toView}}"> <block wx:for="{{detail}}" wx:key="{{item.id}}"> <scroll-view class="cate-box" id="{{item.id}}" scroll-y> <view class="cate-banner" bindtap="bannerDetails"> <image src="{{item.banner}}"></image> </view> <view class="cate-title"> <text>{{item.title}}</text> </view> <view class="cate-product"> <view class="product-list" bindtap="productDetails" wx:for="{{item.productList}}" wx:key="{{index}}" wx:for-item="product"> <image src="{{product.thumb}}"></image> <view class="product-list-name"> <text>{{product.name}}</text> </view> </view> </view> </scroll-view> </block> </scroll-view> </view> //css代码就不放了,手动撸的有点多,如有需要可以去github里拿 //js相关代码 switchCategory(e) { console.log(e) this.setData({ toView:e.currentTarget.dataset.id }) },
看完这个效果以后我就觉得好low啊。。最蛋疼的是右边竟然可以上下滚动,这样一来,右边的商品内容多的时候就会形成两个scroll-view的嵌套,导致用户体验极不友好。
于是无脑的查看了小程序文档以后,我发现swiper组件和scroll-view一样还有一个纵向滑动的属性vertical,而且是有swiper的过渡效果,使得切换的时候不会太僵硬。于是我更改了部分wxml代码,实现了下图中右边不能上下滚动,只能依靠左侧的nav来切换的效果
代码:
<view class="main"> <scroll-view class="menu-left" scroll-y scroll-with-animation="{{true}}"> <view class="cate-list {{curIndex==index?'on':''}}" wx:for="{{menu}}" wx:key="{{item.id}}" data-id="{{item.id}}" data-index="{{index}}" bindtap="switchCategory"> <text>{{item.name}}</text> </view> </scroll-view> <swiper vertical="true" class="menu-right" current="{{toView}}" > <swiper-item wx:for="{{detail}}" wx:key="{{item.id}}"> <scroll-view class="cate-box" id="{{item.id}}" scroll-y> <view class="cate-banner" bindtap="bannerDetails"> <image src="{{item.banner}}"></image> </view> <view class="cate-title"> <text>{{item.title}}</text> </view> <view class="cate-product"> <view class="product-list" bindtap="productDetails" wx:for="{{item.productList}}" wx:key="{{index}}" wx:for-item="product"> <image src="{{product.thumb}}"></image> <view class="product-list-name"> <text>{{product.name}}</text> </view> </view> </view> </scroll-view> </swiper-item> </swiper> </view> //js相关代码 switchCategory(e) { console.log(e) this.setData({ curIndex: e.currentTarget.dataset.index?e.currentTarget.dataset.index:0, toView:e.currentTarget.dataset.index, }) },
6. 微信小程序购物车商品左滑删除功能
在这里我给出一种实现购物车商品左滑删除的方法,给大家参考,直接放代码吧
demo代码:
wxml: <view class="{{item.isTouchMove ? 'touch-move-active' : ''}}" wx:for="{{lists}}" wx:key="{{index}}" data-index="{{index}}" bindtouchstart="touchstart" bindtouchmove="touchmove"> <view class="content">{{item.tt}}</view> <view class="del" catchtap="del">删除</view> </view> wxss: .del { background-color: #b4282d; width: 90px; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #fff; -webkit-transform: translateX(90px); transform: translateX(90px); -webkit-transition: all 0.4s; transition: all 0.4s; } .content { float: left; width: 100%; margin-right:0; -webkit-transition: all 0.4s; transition: all 0.4s; -webkit-transform: translateX(90px); transform: translateX(90px); margin-left: -90px; display: flex; } .touch-move-active .content, .touch-move-active .del { -webkit-transform: translateX(0); transform: translateX(0); }
js部分 data: { lists: [ { tt:'测试', isTouchMove: false }, { tt: '测试', isTouchMove: false }, { tt: '测试', isTouchMove: false }, { tt: '测试', isTouchMove: false }, ] }, // 计算手滑动角度函数 angle: function (start, end) { var _X = end.X - start.X, _Y = end.Y - start.Y //返回角度 /Math.atan()返回数字的反正切值 return 360 * Math.atan(_Y / _X) / (2 * Math.PI); }, touchstart(e) { //开始触摸时 重置所有删除 this.data.lists.forEach(function (v, i) { if (v.isTouchMove)//只操作为true的 v.isTouchMove = false; }) this.setData({ startX: e.touches[0].clientX, startY: e.touches[0].clientY, lists: this.data.lists }) }, //滑动事件处理 touchmove(e) { let index = e.currentTarget.dataset.index;//当前索引 let startX = this.data.startX;//开始X坐标 let startY = this.data.startY;//开始Y坐标 let touchMoveX = e.touches[0].clientX;//滑动变化坐标 let touchMoveY = e.touches[0].clientY;//滑动变化坐标 //获取滑动角度 let angle = this.angle({ X: startX, Y: startY }, { X: touchMoveX, Y: touchMoveY }); this.data.lists.forEach((v, i)=> { v.isTouchMove = false //滑动超过30度角 return if (Math.abs(angle) > 30) return; if (i == index) { if (touchMoveX > startX) //右滑 v.isTouchMove = false else //左滑 v.isTouchMove = true } }) //更新数据 this.setData({ lists: this.data.lists }) }, //删除事件 del(e) { this.data.lists.splice(e.currentTarget.dataset.index, 1) this.setData({ lists: this.data.lists, }) },
大家可以根据自己的需求做相应的修改。放下效果图
7. 微信小程序购物车
购物车页面逻辑的话,要按业务需求来。我这里简单提供一个购物车逻辑的demo,新手可以看下 购物车功能。
结语
商城类微信小程序项目学习github传送门
笔者踩了不少的坑,这里只写出了几个,如果用框架的话会更方便,作为一枚前端的工兵,还是得经常踩坑,才能得到进阶的机会~
第一次写文章,请给新手多一点鼓励,给工兵多一点关爱,点个赞-留下您的建议再走吧~