小程序踩坑之旅

  • 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内定义需要更改值的对象用于接收修改的值(同名)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值