场景一:首页增加下拉刷新功能无效? 经过各种尝试 问题定位到了是因为 在 scroll-view
中使用了 onPullDownRefresh
,最后通过改首页的代码结构达到了预期结果
结论: 在滚动 scroll-view 时会阻止页面回弹,所以在 scroll-view 中滚动,是无法触发 onPullDownRefresh
如果非要在 scroll-view
使用下拉刷新,官方给出的解决方案 是监听页面的滚动事件 bindscroll
厄.. 也是一种方法 只不过我的更粗鲁一些
其他需要注意的:
不要在 scroll-view
中使用 textarea
、map
、canvas
、video
组件
目前只验证过 textarea
暂且放到场景二吧
scroll-into-view
的优先级高于 scroll-top
场景二:无法在 scroll-view 中使用 textarea? 这是个只有在真机上才会出现的 bug
刚开始以为是不能在某些特定的组件内使用textarea
几番尝试 发现是因为 textarea
组件与其他组件的层级关系 后来发现 文档在最下方用最小号的字体给标注出来了已经! 吐血
结论:textarea
组件是由客户端创建的原生组件,他的层级是最高的,在实际项目中 要保证本页面中 无 弹层 之类一切可能会覆盖到页面的鬼。
其他需要注意的:
不要在 scroll-view
中使用 textarea
组件。
css 动画对 textarea 组件无效
textarea 的 blur
事件会晚于页面上的 tap 事件,如果需要在 button 的点击事件获取 textarea,可以使用 form
的 bindsubmit。
官方遗留 bug: textarea
在列表渲染时,新增加的 textarea 在自动聚焦时的位置计算错误。场景三:textarea 的 placeholder 不固定的问题
当把textarea
放到一个 position:fixed
中的元素中时,会发现这个textarea
也会跟着固定位置,但是textarea
的 placeholder 内容不会固定,当滚动页面时,placeholder 的内容会跟着滚动
解决方式:给textarea
组件增加属性 fixed
结论:踩坑大法好
场景四:微信小程序的兼容问题 wx.request()
返回的状态码 res.statusCode
的值 在 IOS 下是 init 型的数据 但是在 Android 6.0.1 上却是 String 型数据 要特别注意判断状态码的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 X wx.request({ url: 'http://api.example.com', success: function (res) { if (res.statusCode === 200) { // success } else { // server failure } } }) 像这样使用 === 就错了 不要判断类型 使用 ==即可
小程序的 WXML 没有 HTML 的宽容度那么高,单标签必需是 /> 结尾的 不然会报错。
场景五:小程序版本的兼容问题 无论用哪个组件 必须时刻注意当前兼容的版本 做低版本兼容
1 2 3 4 5 6 7 8 wx.openBluetoothAdapter() } else { // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示 wx.showModal({ title: '提示', content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。' }) }
Fundebug
能够实时监测小程序,捕获小程序 Bug,然后反馈给开发者Fundebug
场景六:小程序版本的兼容问题 绑定事件的时候,当两个方法重名时,后面的方法会覆盖前面的方法,并且 IDE 不报错
场景七:image 小程序的 image 与 HTML5 的 img 最大的区别在于: 小程序的 image 是按照 background-image
来实现的。 默认 image 的高宽是 320*240。必须通过样式定义去覆盖这个默认高宽,auto 在这里不生效。开发者说这样设置的原因是:如果设置 auto ,页面布局会因为图片加载的过程有一个闪的现象(例如高度从 0 到 height ),所以要求一定要设置一个宽度和高度。
图片包括三种缩放模式 scaleToFill、aspectFit、aspectFill 和 9 种裁剪模式,三种缩放模式的实现原理对应如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 scaleToFill{ background-size:100% 100%;//不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 } aspectFit{ background-size:contain;//保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。 } aspectFill{ background-size:cover;//保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。 }
场景八:navigator navigator 支持相对路径和绝对路径的跳转,默认是打开新页面,当前页面打开需要加 redirect; navigator 仅支持 5 级 页面的跳转; navigator 不可跳转到小程序外的链接地址;
1 <navigator class="navigator" redirect url="../login/index" >登录页</navigator>
在小程序开发工具里,默认打开新页面,工具左上角有返回按钮。加上 redirect,当前页打开,不出现返回按钮。
场景八:大胆使用 flex 布局 在做传统 H5 的时候,为了兼容各种低端设备的机型,通常不太敢轻易尝试 flex,但在小程序里就可以大胆的使用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 .media { display: flex; justify-content:center; align-items:center; } .media .content { flex: 1; }
场景八:大胆使用 flex 布局 在做传统 H5 的时候,为了兼容各种低端设备的机型,通常不太敢轻易尝试 flex,但在小程序里就可以大胆的使用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 .media { display: flex; justify-content:center; align-items:center; } .media .content { flex: 1; }
场景八:页面最后一个 view 组件 设置 margin-bottom 属性 IOS 机型 失效的问题 解决方式:当前 view 当前组件下加一个同级 view
1 2 3 4 5 6 7 8 9 10 11 12 wxml <view>这是个按钮</view> <view class="marginB"></view> css .marginB{ height: 0rpx; font-size: 0rpx; }
场景九:实现长按保存图片 短按图片隐藏 现有问题 用户体验不佳 长按需要抬起才能弹出 sheetAction
菜单
理想状态下是长按开始计时 350 秒之后自动弹操作菜单
利用 bindtouchstart
与 bindtouchend
事件结合 bindtap
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 问题代码一 WXML <view bindtouchstart="mytouchstart" bindtouchend="mytouchend" bindtap="editAddress" > JS editAddress: function (event) { let that = this; //触摸时间距离页面打开的毫秒数 var touchTime = that.data.touch_end - that.data.touch_start; console.log(touchTime); //如果按下时间大于350为长按 if (touchTime > 350) { //TODO.. } else { //TODO.. } }, //按下事件开始 mytouchstart: function (e) { let that = this; that.setData({ touch_start: e.timeStamp }) console.log(e.timeStamp + '- touch-start') }, //按下事件结束 mytouchend: function (e) { let that = this; that.setData({ touch_end: e.timeStamp }) console.log(e.timeStamp + '- touch-end') }
改进
小程序的事件触发顺序
单击 touchstart → touchend → tap 双击 touchstart → touchend → tap → touchstart → touchend → tap 长按 touchstart → longtap → touchend → tap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 问题代码二 wxml <view bindlongtap="longPress" bindtap="tapFun" style="width: 100%;height:100%" mode="scaleToFill" src="{{img_url}}"></view> js longPress(e){ var that = this; console.log('你点击了长按时间',e) // 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope wx.getSetting({ success(res) { console.log('222222222222222222') if (!res['scope.writePhotosAlbum']) { wx.authorize({ scope: 'scope.writePhotosAlbum', success() { // 调起操作菜单 console.log('33333333333333333333') console.log('wx.showActionSheet()',wx.showActionSheet) wx.showActionSheet({ itemList: ['保存到本地'], success: function(res) { console.log('操作菜单弹出成功','第'+res.tapIndex+'个操作菜单弹出成功') // 下载文件资源到本地。客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径。 if(res.tapIndex ==0){ console.log('wx.downloadFile',wx.downloadFile) wx.downloadFile({ url: that.data.img_url, //仅为示例,并非真实的资源 success: function(res) { wx.playVoice({ filePath: res.tempFilePath }); console.log('wx.playVoice()',wx.playVoice) console.log('将图片先保存到本地--res.tempFilePath',res.tempFilePath); // 用户已经同意小程序使用功能,后续调用 wx.startRecord 接口不会弹窗询问 console.log('wx.saveImageToPhotosAlbum()',wx.saveImageToPhotosAlbum) wx.saveImageToPhotosAlbum({ filePath:res.tempFilePath, success(res) { wx.showToast({ title: '保存成功', icon: 'success' }); setTimeout(function(){ wx.hideToast(); },3000) }, fail(res){ wx.showToast({ title: '保存失败', icon: 'success' }); setTimeout(function(){ wx.hideToast(); },3000) } }) } }) } }, fail: function(res) { console.log('操作菜单弹出失败',res.tapIndex) } }) } }) } } }) }, tapFun: function(event) { that.setData({ qrShow:false }) } 很显然 这也是有问题的 因为事件机制。总会触发 tap事件 表现形式比 问题一还难以接受
好了,结合前两种 解决办法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 WXml <image wx:if="{{img_url !=''}}" bindlongtap="editAddress1" bindtouchstart="mytouchstart" bindtouchend="mytouchend" style="width: 100%;height:100%" mode="scaleToFill" src="{{img_url}}"></image> js //按下事件开始 mytouchstart:function(e){ let that = this; that.setData({ touch_start: e.timeStamp }) console.log(e.timeStamp + '- touch-start') }, //按下事件结束 mytouchend:function(e){ let that = this; that.setData({ touch_end: e.timeStamp }) console.log(e.timeStamp + '- touch-end') that.editAddress(e); }, // 判断是长按操作还是短按操作 editAddress: function(event) { var that = this; if(that.data.touch_end - that.data.touch_start < 350){ that.setData({ qrShow:false }) } }, editAddress1(e){} // 同问题二 longPress()
场景十:第二次扫码进入小程序的缓存问题