- bug[1] 商城购物车手动修改商品数量
1.需求展示
2.渲染代码结构
<view class="pro_info clearfix {{goodsItem.goodsState == 30?'gray':''}}">
<view class="pro_title" data-goodsid='{{goodsItem.goodsId}}' bindtap='toDetail'>{{goodsItem.goodsName}}</view>
<view class='pro_price'><text class='f24'>¥</text>{{goodsItem.goodsPrice}}</view>
<view class="num_box {{goodsItem.goodsState == 30?'forbidSel':''}}">
<view class='minus' data-method='minus' data-state='{{goodsItem.goodsState}}' data-quantity='{{goodsItem.buyingNum}}' data-goodsid="{{goodsItem.goodsId}}" data-atype='{{goodsItem.aType}}' data-aid='{{goodsItem.aId}}' bindtap='changeGoodsCount'>
<text class='iconfont icon-jian'></text>
</view>
<!-- 手动修改值部分开始 -->
<view class='ipt_box'>
<input type="number" value='{{goodsItem.buyingNum}}' data-maxnum='{{goodsItem.goodsStorage}}' data-goodsId='{{goodsItem.goodsId}}' data-atype="{{goodsItem.aType}}" data-quantity="{{goodsItem.buyingNum}}" data-aid="{{goodsItem.aId}}" bindblur='getNum' bindinput='getbNum' />
</view>
<!-- 手动修改值部分结束 -->
<view class='add' data-method='add' data-st='{{goodsItem.goodsStorage}}' data-quantity='{{goodsItem.buyingNum}}' data-goodsid="{{goodsItem.goodsId}}" data-state='{{goodsItem.goodsState}}' data-atype='{{goodsItem.aType}}' data-aid='{{goodsItem.aId}}' bindtap='changeGoodsCount'>
<text class='iconfont icon-jia'></text>
</view>
</view>
<block wx:if="{{item.proInfo.aType == 'FG' && item.proInfo.aCondition <= goodsItem.buyingNum}}">
<view class='fg_tips'>
<text class='a_text2' wx:if="{{item.proInfo.proGoodsName}}">【赠品】{{item.proInfo.proGoodsName}}</text>
<text class='a_pric' wx:if="{{item.proInfo.aMessageUnit}}">{{item.proInfo.aMessageUnit}}</text>
</view>
</block>
</view>
3.执行方法
getbNum(e){//bindinput事件实时监听input框的值,并完成实时更改
var goodsId = e.target.dataset.goodsid;
for (var k in this.data.goodsList) {
var goodsInfo = this.data.goodsList[k].goodsInfo;
for (var j in goodsInfo) {
if (goodsInfo[j].goodsId == goodsId) {
goodsInfo[j].buyingNum = e.detail.value;
this.setData({
goodsList: this.data.goodsList
})
}
}
}
},
getNum(e) {//判断商品数量关系,做出对应提示,同时发送请求
var max_buy = e.target.dataset.maxnum;
var goodsId = e.target.dataset.goodsid;
var aType = e.target.dataset.atype;
var aId = e.target.dataset.aid;
var quantity = 0;
if (e.detail.value <= 0) {
quantity = 1;
wx.showToast({
icon: 'none',
title: '一件起购'
});
} else if (e.detail.value >= max_buy && max_buy != 0) {
quantity = max_buy;
wx.showToast({
icon: 'none',
title: '当前商品限购数量' + max_buy
});
} else {
quantity = e.detail.value;
}
let data = {
"goods_id": goodsId,
"aType": aType,
"aId": aId,
"quantity": quantity
}
var _this = this;
dfs.ajaxItem('cart/update', "GET", data, function(res) {
console.log('aaaa')
_this.setData({
showTypeBox: false
})
_this.getCartList("n");
})
},
4.bug总结
→→→ 像小程序这种以双线程驱动的编程方式,当用数据量巨大,且层级嵌套复杂的数据来驱动试图,并且反向改变数据时使用到发送请求这种情况
时,一定要注意区分bindinput事件和bindblue事件的执行顺序,在处理购物车手动输入商品数量的需求时,如果只使用bindinput事件来处理全
部的业务逻辑,会造成频繁的发送请求,造成不可预估的错误(当然还是使用定时器),而只使用bindblue事件;来处理时,虽然杜绝了频繁发送请求
带来的问题,但是,实时获取输入框的值变的困难了起来,特别是数据量大这种现实情况.
→→→ 实现方式:分步处理,把业务实现分为两个层面,让输入框的value用bindinput来实时监控和更改,让bindblur来处理库存和数值的关系以及
发送相关请求.
→→→ 在编译时,使用电脑和使用手机不同,安卓机的键盘收起事件也会让bindblur事件中获取的值正确,所以在处理时记得真机调试.
-
bug[2] 视频标签层级问题 视频播放中商品列表置顶
1.需求展示
需求: 视频播放时点击查看更多商品按钮时,视频有声音,商品列表置顶,反之亦然2.初步实现方案
<!-- 视频部分 --> <view class="video_box"> <view class="video_play"> <view wx:if="{{!hasVideo}}" bindtap="videoPlay"> <block wx:if="{{networkType=='wifi'}}"> <block wx:if="{{(detailInfo.vidDetail.ongoing==3&&detailInfo.vidDetail.vUrl=='')||(detailInfo.vidDetail.ongoing==2&&detailInfo.vidDetail.pvUrl == '')}}"> <image class="vedio_tips" src='https://oss-image.dfs168.com/market/183/vedio_tips.png'></image> </block> <block wx:else> <image class="cover_img" src='{{detailInfo.vidDetail.image}}'></image> <text class='mengceng1'></text> <image class="play_btn" src="https://oss-image.dfs168.com/market/183/bofang.png" /> </block> </block> <block wx:else> <view wx:if="{{!hasVideo}}" class="tips_box"> <view class='h4'>正在使用非WiFi网络,播放将产生流量费用</view> <block wx:if="{{(detailInfo.vidDetail.ongoing==3&&detailInfo.vidDetail.vSize>0)||(detailInfo.vidDetail.ongoing==2&&detailInfo.vidDetail.pvSize > 0)}}"> <view class='p'> <image src='https://oss-image.dfs168.com/market/183/play_icon.png'></image>{{detailInfo.vidDetail.ongoing==2?detailInfo.vidDetail.pvSize:detailInfo.vidDetail.vSize}}流量 </view> </block> <block wx:else> <image style='width:60rpx; height:60rpx;' src='https://oss-image.dfs168.com/market/183/bofang.png'></image> </block> </view> </block> </view> <video wx:if="{{hasVideo}}" id="myVideo" src="{{detailInfo.vidDetail.ongoing==2 ? detailInfo.vidDetail.pvUrl : detailInfo.vidDetail.vUrl}}" poster='{{detailInfo.vidDetail.image}}' id="myVideo" controls></video> </view> </view> <!-- 视频部分结束 --> <!-- 给视频添加一个外层标签,用外层标签来控制视频标签的层级,发现安卓机可以实现,ios不行 -->
3.bug解决方案
给视频标签添加样式控制,点击时让视频出现在可视区以外的地方,反之亦然.4.bug总结
ios自带浏览器使视频标签只要存在就会是最高层级,视图中如果滚动的是body会使得带动上下底部,视频也会随着内容滚动发生位置脱离现象,所以在处理兼容问题时,页面中的滚动元素不要是body,而应该是内部盒子滚动,建议微信滚动div,小程序使用scroll-view滚动,视频层级过高,只能采取加视频蒙层,视频播放时展示,如果视频需要一直播放,只能使用样式控制的方式. -
bug[3] 长按保存图片识别二维码问题 小程序不能长按识别二维码
1.需求展示
2.渲染代码结构<view hidden='{{isCode}}' class="shade_box none"> <view class="code_bg"> <!-- <image bind:longpress='onImgOK' src="{{buQrcode}}" alt="" /> --> <image bind:longpress='onImgOK' src="{{buQrcode}}" alt="" /> <view class='p'>保存二维码,打开扫一扫,马上看直播</view> </view> <image bindtap='closeCode' class="closed_btn" src="http://image.dfs168.com/market/183/close_icon.png" alt="" /> </view>
3.执行方法
//长按保存二维码 onImgOK(e) { this.getAuth();//授权 var _this = this; this.imagePath = e.currentTarget.dataset.path; if (_this.data.openBtn) { return false; } console.log('保存') _this.data.openBtn = true; wx.downloadFile({ url: _this.imagePath, success(res) { if (res.statusCode === 200) { wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: function () { wx.hideLoading(); wx.showToast({ title: '保存成功', icon: 'success', duration: 1500 }) }, fail: function () { wx.hideLoading(); wx.showToast({ title: '保存失败,请稍后重试', icon: 'none', duration: 1500 }) }, complete: function () { _this.data.openBtn = false; } }); } } }) }, getAuth() { console.log('执行了') var _this = this; wx.getSetting({ success(res) { console.log(res) if (!res.authSetting['scope.writePhotosAlbum']) { wx.authorize({ scope: 'scope.writePhotosAlbum', success: function (res) { //授权成功 }, fail(res) { wx.showModal({ title: '提示', content: '未授权将不能保存图片', showCancel: false, success(res) { if (res.confirm) { _this.openSetting() } } }) } }) } } }) }, openSetting() { wx.openSetting({ success(res) { console.log(res.authSetting) } }) },
4.bug解决方案
wx.saveImageToPhotosAlbum的使用需要注意授权,且图片地址为本地图片,所以需要使用 wx.downloadFile本地化网络图片即可.
5.bug总结
小程序长按保存图片需要的执行首要点就是需要用户授权,且此次授权微信会记住,一经取消,就会记住,无法再次调用授权事件wx.getSetting,所以一般处理方式是引导用户去设置中修改权限设置,此次处理中地调用了wx.openSetting(点击触发) -
bug[4] 异步请求中给组件传值 请求再异步
1.需求展示
小调差弹框组件要在首页其他弹框关闭之后出现,弹框是否出现需要接口请求得知
2.渲染代码结构<!-- 组件引用 --> <makeTag id="makeTag" wx:if="{{ismakeTag}}"></makeTag> <!-- 组件部分 --> <view hidden="{{!isShow}}"> <view class="shade" wx:if="{{crop.length>0}}"> <view class="content"> <text class='h4'>小调查</text> <image class="close_btn" src="http://image.dfs168.com/market/280/close_img.png" alt="" catchtap="closeBox" /> <view class="choice_box"> <view class='p'> 对于“大丰收农资商城公众号”给您发送的农技文章, <text class='span'>您最希望看到哪个作物的呢?</text> </view> <view class="options clearfix"> <view class="{{item.tag_id==conCrop?'active li':'li'}}" wx:for="{{crop}}" wx:key="{{index}}" data-item='{{item.tag_id}}' catchtap="getCrop">{{item.tag_name}}</view> </view> </view> <a href="javascript: ;" class="check_btn" catchtap="submitCrop">确 定</a> </view> </view>
3.执行方法
<!-- 引入页面 -->
onReady() {
this.makeTag = this.selectComponent("#makeTag");//获取子组件实例对象(this.selectComponent方法)
this.makeTag.setData({ //打标
isShow: true
})
},
<!-- 组件页面处理 -->
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
// if (wx.getStorageSync("token")) {
// this.getCropList()
// }
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
console.log('组件实例被从页面节点树移除时执行')
},
},
methods: {
getCropList() {
var _this = this;
app.request({
url: `${app.globalData.API_URL}/activity/wx-tag-collect/crop-list`,
method: 'GET',
success: function(res) {
console.log(res, '打标记录')
if (res.error == 0) {
if (res.data.tagList && (res.data.tagList.length > 0)) {
_this.setData({
crop: res.data.tagList
})
}
} else {
_this.setData({
crop: []
})
}
}
})
},
...
}
})
4.bug解决方案
使用this.selectComponent方法获取组件实例,通过控制实例中的属性和方法控制组件
5.bug总结
小程序组件之间的通信方式和vue相同,父组件给子组件传值使用数据绑定传值,子组件在properties中取值,子组件给父组件传值时,绑定自定义事件.
使用数据传值需要在传值的当下,值必须是确定的.特别是一些状态的控制,子组件中没有watch,不能实时监听传递至的改变,所以解决这次需要延时请求后才能回去值的情况,只能在进入页面控制组件状态,所以需要使用this.selectComponent方法,获取组件示例,点出属性值.由于是双重请求,组件在控制时,应该是两个包含式的变量控制,组件是请求控制的,所以在离开页面是需要卸载组件.
- bug[5] tab栏切换定位 dom元素距离顶部的距离
1.bug解决
const query = wx.createSelectorQuery()
query.select('#dom-id').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec(function(res){
//res[0].top // #the-id节点的上边界坐标
//res[1].scrollTop // 显示区域的竖直滚动位置
wx.pageScrollTo({
scrollTop: res[0].top + res[1].scrollTop, //滚动距离
duration: 600
})
})
- bug[6] 小程序码传值 只能在场景值处取值
1.wxacode.getUnlimited
获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。
2.传参方式
3.前端扫码处理
//当传入场景值为扫码进入(1047)时
//生成小程序码携带参数时(参数存放在场景值字段)
//当前页面可以直接在option.scene中取值
//小程序码扫描进入时,参数会在场景值处传递,键值对编码成字符为值传入(如图)
//取值方式
onLoad: function (options) {
const scene = decodeURIComponent(options.scene); //字符串
var sceneArr = [];
if (scene.indexOf('cch_id=')!=-1){
sceneArr = scene.split('cch_id=');
}
var cch_id = sceneArr[1] || options.cch_id
}
- focus[1] 返回上一页并传值
var pages = getCurrentPages();
var prevPage = pages[pages.length - 2]; //上一个页面
//直接调用上一个页面的setData()方法,把数据存到上一个页面中去
prevPage.setData({
mydata: {
id:1,
b: 125
}
})
wx.navigateBack({//返回
delta: 1
});
//注:返回页面要在data内定义需要更改值的对象用于接收修改的值(同名)