- 同层渲染失败的原因
同层渲染失败一般有两个原因 1.国外渠道下载的微信,目前不支持同层渲染 2.刚更新的微信,还在准备中,请稍后重试 可在组件中监听同层失败回调 bindrendererror 来判断
2020-09-11 - wx.setStorageSync 在部分苹果微信客户端的本地数据库损坏问题
可尝试以下操作:试着删除所有入口的小程序,从我的小程序、最近使用中删除,包括开发版,杀进程然后可重启微信试下, ps(该问题已经修复,等待7.0.7微信客户端上线即可)
2019-11-20 - 小程序多端差异调研报告(微信,支付宝,头条,QQ)
已经使用uni-app开发并发布了一个跨端小程序啦,嘻嘻嘻! 🧐 须知 这是一份详细的小程序各特性各端真机调研对比报告 测试机:iPhone7 plus IOS 12.4.1 客户端:微信7.0.5,支付宝10.1.72,今日头条7.4.0,抖音8.1.0,QQ8.1.5.461 🚫️ 百度小程序只有商户才能注册,个人开发者无法注册,没有appid功能受限(如百度开发者工具无法使用预览功能导致无法真机测试),所以暂时不测百度小程序 用户信息授权 授权方式: 【头条】用户信息授权方式还停留在微信小程序第一版,即直接调用 getUserInfo 弹出授权弹窗,如果用户选择允许,则后续调用不再出弹窗,而是直接走 success 回调。如果用户选择取消,则后续调用也不再出弹窗,而是直接走 fail 回调 【微信】【QQ】【支付宝】则采用 button + 回调事件的方式调起授权弹窗,如果用户选择允许,则后续点击不再出弹窗,直接走回调。如果用户选择取消,则后续点击继续弹窗询问授权 授权信息清除方式: 【微信】删除小程序即可清除授权信息 【支付宝】我的-设置-安全设置-账号授权 【今日头条】我的-系统设置-清除缓存。【抖音】未找到清除方法 【QQ】未找到清除方法(据说开放小程序的QQ版本尚未灰度发布) 小程序登录 【微信】wx.login 【QQ】qq.login 基本同微信 【支付宝】my.getAuthCode 【头条】大致同微信,未找到模型文档 分享 行为: 【微信】直接调起聊天对话列表进行选择 【QQ】调起分享渠道列表: QQ好友 QQ空间 点右上角三个点调起的列表还有微信好友和朋友圈两个项,在微信中打开qq小程序是走中间页 【支付宝】调起分享渠道列表: 支付宝朋友圈 支付宝联系人 微信好友|QQ好友(保存支付宝生成的分享图片后打开支付宝扫码) 钉钉好友(中间页自动打开支付宝小程序,中间页不自动关闭) 新浪微博(中间页自动打开支付宝小程序,和钉钉一个中间页) 【头条】调起分享渠道列列表: 转发到头条 微信好友|微信朋友圈(生成口令,复制口令后打开今日头条弹出识别弹窗) QQ|QQ空间(打开中间页,点击打开(QQ空间点了没反应),出现另一个中间页,自动打开AppStore,再点打开调起今日头条,最后居然没打开那个小程序🥴!!!) 【抖音】调起分享渠道列列表: 多闪好友 微信好友|微信朋友圈|QQ好友|QQ空间(生成抖音码图片,打开抖音扫码识别) 【头条】webview的转发暂未支持: 【今日头条】能转发,但转发的链接点击后总是提示加载失败!也可能是小程序未发布的原因,扫uni-app官方demo进行 webview转发是能正常打开的 【抖音】不支持转发,右上角胶囊只有一个关闭按钮 跳转到其他小程序 【微信】支持(navigateToMiniProgramAppIdList + navigateToMiniProgram) 【QQ】支持 【头条】支持(navigateToMiniProgramAppIdList + navigateToMiniProgram) 【支付宝】支持(后台配置 + navigateToMiniProgram) 🚫️ ️QQ,支付宝和头条未真机验证,因为须要一个其他小程序的appId 客服会话 【微信】支持(button open-type=“contact”) 【QQ】支持,须用户加一个客服机器人为好友 【支付宝】支持(contact-button) 【头条】不支持。 支付 【微信】支持(调起微信支付) 【QQ】支持(调起QQ支付) 【支付宝】支持(调起支付宝支付) 【头条】支持(调起支付宝App进行支付) 🚫 ️QQ,支付宝和头条未真机验证,因为支付接口只有商户才有权限 地理位置 【微信】支持(须在app.json中配置permission字端),用户拒绝授权后再次调用不再出询问弹窗,而是直接走fail回调 【QQ】支持。真机行为同微信。QQ开发者工具上拒绝授权再次调用仍会出询问弹窗 【头条】支持,同微信 【支付宝】支持,用户拒绝授权后再次调用继续出询问弹窗 视频播放 【微信】支持 【QQ】支持 【头条】支持 【支付宝】支持?(uni-app里说支付宝不支持,支付宝文档也没找到video组件,但放在页面里video能正常渲染和播放,难道是昨天刚支持🤔) 复制文字 行为: 【微信】【QQ】复制成功后有一个默认的复制成功toast且无法控制 【支付宝】【头条】复制成功后没有toast 权限: 【支付宝】my.setClipboard 此功能仅支持企业支付宝账号。实际情况是:在IDE上个人账号是可以复制的,但在真机上调用就会报 [代码]ERROR 4: 无权调用该接口[代码] 错误 【微信】【QQ】【头条】无限制 打电话 【微信】【QQ】【支付宝】【头条】都支持 收货地址 【微信】支持 【QQ】不支持 【头条】支持(实测【今日头条】支持,【抖音】不支持) 【支付宝】支持。但仅商户才有使用权限。且目前 my.getAddress 接口暂不支持在开发者工具调试和真机调试,仅支持真机预览 相机/图片相关 拍照/相册选图片 【微信】【QQ】支持 【支付宝】支持。IDE上会弹一个相册授权询问弹窗,真机上并没有弹窗 【头条】支持。但会弹出两个询问弹窗(相机权限,相册权限) 拍摄/相册选视频 【微信】【QQ】支持 【支付宝】支持。IDE上会弹一个相册授权询问弹窗,真机上并没有弹窗。须调用 my.chooseVideo(文档未找到),uni.chooseVideo会报错 【头条】支持。但会弹出两个询问弹窗(相机权限,相册权限) ⚠️chooseVideo的maxDuration选项在【微信】和【支付宝】是只限制拍摄时长,在【头条】是同时限制相册选择视频时长和拍摄时长 图片预览 【微信】【QQ】【支付宝】【头条】都支持 保存图片到相册 【微信】【QQ】【头条】支持,弹窗仅询问一次 【支付宝】tt.saveImageToPhotosAlbum 在IDE上报错 [代码]tt.saveImageToPhotosAlbum is not a function[代码],在真机上报错 [代码]无权调用该接口[代码],文档未提及,猜测是仅商户可用,且不支持在开发者工具调试和真机调试,仅支持真机预览 接口返回值差异 getUserInfo【微信】【QQ】【支付宝 】【头条】 [代码]// 支付宝 { 'nickName': 'test', 'gender': 'm', 'city': '北京市', 'province': '北京' 'countryCode': 'CN', 'avatar': 'https:\/\/tfs.alipayobjects.com\/images\/partner\/T1_38eXnRiXXXXXXXX', 'code': '10000', 'msg': 'Success', } // 微信 { 'nickName': 'test', 'gender': 1, 'city': 'Xinxiang', 'province': 'Henan', 'country': 'China', 'avatarUrl': 'https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJCzUl7llykqrMLicpULvVfkbbL2bVDua4tI8ibjxq5E9ib1oPW3F4QazLIUdS2GsFMAGnrWSYjN05Ew/132' 'language': 'zh_CN', } // QQ { 'nickName': 'test', 'gender': 1, 'city': '新乡', 'province': '河南' 'country': '中国', 'avatarUrl': 'https://thirdqq.qlogo.cn/qqapp/1108100302/D64611B2AE700324589177922EEBA5F4/100', 'language': 'zh_CN', } // 头条系(今日头条,抖音,皮皮虾,西瓜视频分别取各自用户信息) { 'nickName': 'test', 'gender': 1, 'city': '新乡市', 'province': '河南省' 'country': '中国', 'avatarUrl': 'http://wx.qlogo.cn/mmhead/Q3auHgzwzM5uibSytRCXFs0Y3xSpdy12thibjWIoMrBIsf7FiaPp2ibnFg/0', 'language': '', } [代码] getSetting【微信】【支付宝 】【头条】【QQ】 [代码]// 微信 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html [ 'scope.userInfo', // 用户信息 'scope.userLocation', // 地理位置 'scope.address', // 通讯地址 'scope.record', // 录音功能 'scope.camera', // 摄像头 'scope.writePhotosAlbum', // 保存到相册 'scope.userLocationBackground', // 后台定位 'scope.invoiceTitle', // 发票抬头 'scope.invoice', // 获取发票 'scope.werun', // 微信运动步数 ] // 头条 https://developer.toutiao.com/dev/miniapp/uQjMy4CNyIjL0IjM [ 'scope.userInfo', // 用户信息 'scope.userLocation', // 地理位置 'scope.address', // 通讯地址 'scope.record', // 录音功能 'scope.camera', // 摄像头 'scope.album', // *保存到相册* ] // 支付宝 https://docs.alipay.com/mini/api/xmk3ml#-1 [ 'userInfo', // 用户信息 'location', // 地理位置 'audioRecord', // 录音功能 'camera', // 摄像头 'album', // 保存到相册 ] // QQ https://q.qq.com/wiki/develop/game/frame/open-ability/authorize.html [ 'scope.userInfo', // 用户信息 'scope.userLocation', // 地理位置 'scope.qqrun', // QQ运动步数 'scope.writePhotosAlbum', // 保存到相册 'scope.appMsgSubscribed', // 订阅消息 ] [代码] 主要入口 【微信】 首屏对话列表下拉 扫一扫 发现->小程序 搜索 【支付宝】 扫一扫 搜索 首页我的小程序 【今日头条】 我的->扫一扫 搜索 【抖音】 搜索->扫一扫 【QQ】 扫一扫 💣 头条小程序陷阱 目前仅在头条Android版本7.2.9及以上版本支持真机调试功能。iOS暂时不支持真机调试 抖音App的小程序上没有打开调试器选项,右上角胶囊只有一个关闭按钮 💣 支付宝小程序陷阱 my.getOpenUserInfo用于获取支付宝会员基础信息,只能在真机上调试,无法在 IDE 中调试,也就是只要有用户授权的页面都需要推送到真机上开发调试! 支付宝授权平台只返回tocken和uid,由开发者自己维护session有效期,[代码]checkSession[代码] 方法不可用 打开调试的调试器面板在调起用户授权弹窗时会消失,此时须使用真机调试 💣 uni-app 陷阱 uni.getSetting,文档上说【支付宝】支持,调用却报错 [代码]支付宝小程序,暂不支持getSetting[代码],而直接调支付宝的api my.getSetting 确是支持的 uni.chooseVideo,文档上说【支付宝】支持,调用却报错 [代码]支付宝小程序,暂不支持chooseVideo[代码],而直接调支付宝的api my.chooseVideo(文档未找到) 确是支持的 uni.chooseAddress,文档上说【支付宝】不支持,实际上是支持的,只是需要调用 my.getAddress,且仅商户才能使用 uni.getImageInfo,文档上说【头条】支持,调用却报错 [代码]头条小程序,暂不支持getImageInfo[代码],而直接调头条的api tt.getImageInfo 确是支持的 📌 TODO 模版消息 第三方插件 uni-app 跨端小程序风险点 后端接口。不同端的后端接口不一样,需要后端评估一下。举例:模版消息(微信|支付宝|头条);设计用户系统时需注意微信和QQ都有各自的openID和unionID,支付宝只有uid,头条只有openID;接入微信,QQ,支付宝支付时各种传参不一样 分享转发。支付宝,头条小程序分享至微信和QQ的主要方式是生成口令或者生成小程序码图片或者走中间页,导致传播路径较长 某些端重要功能缺失。举例:【头条】不支持客服会话。【抖音】不支持webview转发。【QQ】不支持收货地址 某些端api缺失,可能导致某些功能无法实现 第三方插件支持度
2019-11-02 - [填坑手册]小程序新版订阅消息+云开发实战与跳坑
[图片] 老版本的订阅消息在2020年1月10日就下线了,相信不少人在接入新版本订阅系统的时候,或多或少会遇到一些问题,这里智库君跟大家介绍下新版订阅的机制和不需要node/后端的情况下 独立完成功能开发。 一、新版订阅的机制 其实开发过程不难,但是要理清楚它里面的机制,智库君还是花了一些时间的,也踩了不少坑 先来看下官方介绍: [图片] 可以设置多个订阅选项 感叹号里面可以看到详情 有个默认不被选中的“总是”选项 这些就是新不同的地方,智库君在开发的时候也有很多疑问,点了“总是”再点“取消”按钮会怎样?部分选择订阅会怎样?下面为大家一一梳理 (1)部分选中 [图片] 比如现在有三个选项 A,B,C,用户**“部分选中”**返回的情况: [图片] 这里用真机调试可以看到,有个返回值状态为“reject”。 如果我们反复几点点击同一个订阅后,这些值是如何计算的呢? 举例: [图片] 从这里看出,微信系统会自动记录用户点击的次数,并且做累加记录,如果用户只允许2次发送,而开发者发送了3次,最后一次将会被拒绝。 (2)点击“总是保持以上选择,不再询问”的情况 [图片] 当用户点击“总是”之后,同一个类型的订阅将不再弹出,那如果有多个订阅选项呢? 举例 订阅AAA 三个订阅模板为 X Y Z 订阅BBB 二个订阅模板为 Y W 这时候如果“订阅AAA”按钮选择了“总是”,那么再点击“订阅BBB”按钮,将只会弹出一个选项“W”,不会有 “Y” 的模板,因为在之前 “订阅AAA” 按钮中已经包含了。 [代码]wx.requestSubscribeMessage({ tmplIds: ["MECDDOdhbC3SrQmMY5XrfqiIGbMTzpEN8Z7ScXJfcd0", "iSb2NIlNnnO60wlI-8Wx5Pe82jR7TRdwjotSXtM1-ww"], success(res) { console.log(res); } }) [代码] 显示内容仅一个选项: [图片] 这里需要注意,“总是”选项是全局有效,不区分页面,选中“总是”的 W,X,Y,Z的模板,在全局任意页面中再次调用,再次调用将不再会显示! [图片] 返回值无提示用户是否选中“总是”。 (3)用户点击“总是”后,获取状态 [图片] [代码]wx.getSetting({ withSubscriptions: true, success(res) { console.log(res.authSetting) // res.authSetting = { // "scope.userInfo": true, // "scope.subscribeMessage": true // } console.log(res.subscriptionsSetting) // res.subscriptionsSetting = { // SYS_MSG_TYPE_INTERACTIVE: 'accept', // SYS_MSG_TYPE_RANK: 'accept', // zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: 'reject', // ke_OZC_66gZxALLcsuI7ilCJSP2OJ2vWo2ooUPpkWrw: 'ban', // } } }); [代码] [图片] 这里可以调用wx.getSetting方法,但是需要注意:如果用户第一次选“总是”后点击“取消”按钮或者订阅模板全部是未选中/reject的,那将获取不到状态(这里可能是BUG,期待官方未来修复)。 (4)用户点击“总是”后,让用户手动修改 前面说到用户点击“总是”后,系统将不再弹窗,但是我们可以通过**“wx.openSetting”**引导用户手动修改。 [代码]wx.openSetting({ success(res) { console.log(res.authSetting) // res.authSetting = { // "scope.userInfo": true, // "scope.userLocation": true // } } }) [代码] [图片] [图片] 当然用户自己也可以修改 [图片] 总结 【重点】选择“总是”,很多人认为就可无限发送订阅消息,这个是错误的,勾选和不勾选唯一的区别就是每次触发订阅的时候会不会弹授权窗口!!! 用户点击次数系统会自动累加,直接影响后台发送通知的次数。 用户选择“总是”后,小程序界面不再弹窗,但仍然有回调/callback。 任意订阅模板在用户选中“总是”(包括接受/拒绝2个状态)后,全局有效,就算其他订阅包含“此模板”也不再显示/弹出 当用户选择“总是”中“accept/选中/接受”的状态后,可以在wx.getSetting查询到用户是否选择“总是”。 当用户选择“总是”中“reject/未选中/拒绝”的状态后,返回值“无感知”(这里可能是BUG) 二、功能开发 使用微信自带的云开发,可以在没有node/后端开发支持下,完成整个订阅流程的开发。 (1)微信后台设置订阅模板和获取模板ID 1、打开小程序后台,找到订阅消息设置 [图片] 2、在公共模板库找模板或者自己申请新模板,建议能用现成模板用现成的,因为申请周期可能较长,且容易被拒 [图片] 3、选好模板后,点击详情 [图片] 4、查看模板内容和发送DATA的结构 [图片] 5、复制模板ID (2)配置云函数 [图片] [图片] 1、新建getOpenId云函数,用于获取用户的openID [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() return { event, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } } [代码] 2、新建订阅推送通知云函数 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() //订阅推送通知 exports.main = async (event, context) => { try { const result = await cloud.openapi.subscribeMessage.send({ touser: event.openid, //接收用户的openId page: 'pages/my/index', //订阅通知 需要跳转的页面 data: { //设置通知的内容 thing1: { value: '小程序订阅填坑' }, thing2: { value: '智库方程式' }, thing3: { value: '一起学习,一起进步' } }, templateId: '5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac' //模板id }) console.log(result) return result } catch (err) { console.log(err) return err } } [代码] 写完云函数记得右键部署下!!! (3)小程序代码部分 [代码]<!------------html -------------> <button bindtap="getOpenId" type='primary'>获取openId</button> <view class="subBtn" catch:tap="sub">订阅AAA</view> <view class="subBtn" catch:tap="send">订阅推送测试</view> <view class="subBtn" catch:tap="setting">设置“总是”后,跳转修改</view> [代码] [代码]//JS 部分 //获取用户的openid getOpenId() { wx.cloud.callFunction({ name: "getOpenId" }).then(res => { let openid = res.result.openid console.log("获取openid成功", openid) }).catch(res => { console.log("获取openid失败", res) }) }, //发送模板消息给指定的openId用户 send(openid){ wx.cloud.callFunction({ name: "sendSub", data: { openid: openid } }).then(res => { console.log("发送通知成功", res) }).catch(res => { console.log("发送通知失败", res) }); }, //消息订阅 sub: function () { wx.requestSubscribeMessage({ tmplIds: ["5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac"], success(res) { console.log("订阅授权成功:"+res); }, fail(res){ console.log("订阅授权失败:" + res); } }) }, //帮助用户跳转修改订阅状态 setting:function(){ wx.openSetting({ success(res) { console.log(res.authSetting) // res.authSetting = { // "scope.userInfo": true, // "scope.userLocation": true // } } }) }, [代码] (4)测试流程 点击发送通知后,获得这样的效果: [图片] [图片] 获得对应返回值: [图片] 当errCode为0时,即发送通知成功。 当errCode为43101,说明用户只授权了一次,但是你发送了2次,超过用户授权次数。 [图片] 三、进阶与思考 1、当你有多个订阅模板同时需要用户选择时,你可以通过以下代码记录,用户哪些选了,哪些没选。 [代码]wx.requestSubscribeMessage({ tmplIds: ["5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac", "OBB_Z10eh_Inm9p8EU6Ml_NS_mijXgTz3T07cxgKvX0","5Efr7IqIooYO9nPw047Iggxbm9Ge2Km10GQ4amGOUac"], success(res) { //console.log(res); if (res.errMsg == "requestSubscribeMessage:ok") { let acceptArray = []; //用户授权模板列表 for (let i = 0; i < tmplIds.length; i++) { const element = tmplIds[i]; if (res[element] == "accept") { acceptArray.push(element); } }; console.log(acceptArray); if (acceptArray.length > 0) { //执行下一步函数 } } } }) [代码] 2、一个关于是否需要记录用户对某个“订阅模板授权的次数”,以控制后台“发送的次数”,智库君在实战中认为,其实没有必要,顶多就是你发送返回一个错误码,微信之所有记录用户授权次数,也是为了保护用户不被骚扰。 3、你只需要记录用户点击了哪些需要授权的模板就行,为了是用户点击订阅后,改变按钮的状态,避免订阅按钮反复弹窗的问题,同时当检测到用户点错“总是”按钮后,可以自动跳转到“设置”界面。 4、这次智库君主要给大家简单介绍了下订阅全流程。后面大家可以根据自己的需要,添加和改进这些代码。比如: 配置云函数中的node函数,实现定时发送 配置云函数中的数据库,实现内容的自定义发送 最后,希望这篇文章能帮助到大家,一起学习,一起进步! (官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html) 往期回顾: [打怪升级]小程序自定义头部导航栏“完美”解决方案 [填坑手册]小程序Canvas生成海报(一) [拆弹时刻]小程序Canvas生成海报(二)
2021-09-13 - [有点炫]自定义navigate+分包+自定义tabbar
自定义navigate+分包+自定义tabbar,有需要的可以拿去用用,可能会存在一些问题,根据自己的业务改改吧 大家也可以多多交流 代码片段:在这里 {"version":"1.1.5","update":[{"title":"修复 [复制代码片段提示] 无法使用的问题","date":"2020-06-15 09:20","imgs":[]}]} 更新日志: 2019-11-25 自定义navigate 也可以调用wx.showNavigationBarLoading 和 wx.hideNavigationBarLoading 2019-11-25 页面滚动条显示在自定义navigate 和 自定义tabbar上面的问题(点击“体验custom Tabbar” [图片] [图片] 其他demo: 云开发之微信支付:代码片段
2020-06-15 - 有赞前端质量保障体系
前言 最近一年多一直在做前端的一些测试,从小程序到店铺装修,基本都是纯前端的工作,刚开始从后端测试转为前端测试的时候,对前端东西茫然无感,而且团队内没有人做过纯前端的测试工作,只能一边踩坑一边总结经验,然后将容易出现问题的点形成体系、不断总结摸索,最终形成了目前的一套前端测试解决方案。在此,将有赞的前端质量保障体系进行总结,希望和大家一起交流。 先来全局看下有赞前端的技术架构和针对每个不同的层次,主要做了哪些保障质量的事情: [图片] [图片] 有赞的 Node 技术架构分为业务层、基础框架层、通用组件和基础服务层,我们日常比较关注的是基础框架、通用组件和业务层代码。Node 业务层做了两件事情,一是提供页面渲染的 client 层,用于和 C 端用户交互,包括样式、行为 js 等;二是提供数据服务的 server 层,用于组装后台提供的各种接口,完成面向 C 端的接口封装。 对于每个不同的层,我们都做了一些事情来保障质量,包括: 针对整个业务层的 UI 自动化、核心接口|页面拨测; 针对 client 层的 sentry 报警; 针对 server 层的接口测试、业务报警; 针对基础框架和通用组件的单元测试; 针对通用组件变更的版本变更报警; 针对线上发布的流程规范、用例维护等。 下面就来分别讲一下这几个维度的质量保障工作。 一、UI 自动化 很多人会认为,UI 自动化维护成本高、性价比低,但是为什么在有赞的前端质量保证体系中放在了最前面呢? 前端重用户交互,单纯的接口测试、单元测试不能真实反映用户的操作路径,并且从以往的经验中总结得出,因为各种不可控因素导致的发布 A 功能而 B 功能无法使用,特别是核心简单场景的不可用时有出现,所以每次发布一个应用前,都会将此应用提供的核心功能执行一遍,那随着业务的不断积累,需要回归的测试场景也越来越多,导致回归的工作量巨大。为了降低人力成本,我们亟需通过自动化手段释放劳动力,所以将核心流程回归的 UI 自动化提到了最核心地位。 当然,UI 自动化的最大痛点确实是维护成本,为降低维护成本,我们将页面分为组件维度、页面维度,并提供统一的包来处理公用组件、特殊页面的通用逻辑,封装通用方法等,例如初始化浏览器信息、环境选择、登录、多网点切换、点击、输入、获取元素内容等等,业务回归用例只需要关注自己的用例操作步骤即可。 1、框架选择 – puppeteer[1],它是由 Chrome 维护的 Node 库,基于 DevTools 协议来驱动 chrome 或者 chromium 浏览器运行,支持 headless 和 non-headless 两种方式。官网提供了非常丰富的文档,简单易学。 UI 自动化框架有很多种,包括 selenium、phantom;对比后发现 puppeteer 比较轻量,只需要增加一个 npm 包即可使用;它是基于事件驱动的方式,比 selenium 的等待轮询更稳当、性能更佳;另外,它是 chrome 原生支持,能提供所有 chrome 支持的 api,同时我们的业务场景只需要覆盖 chrome,所以它是最好的选择。 – mocha[2] + mochawesome[3],mocha 是比较主流的测试框架,支持 beforeEach、before、afterEach、after 等钩子函数,assert 断言,测试套件,用例编排等。 mochawesome 是 mocha 测试框架的第三方插件,支持生成漂亮的 html/css 报告。 js 测试框架同样有很多可以选择,mocha、ava、Jtest 等等,选择 mocha 是因为它更灵活,很多配置可以结合第三方库,比如 report 就是结合了 mochawesome 来生成好看的 html 报告;断言可以用 powser-assert 替代。 2、脚本编写 封装基础库 封装 pc 端、h5 端浏览器的初始化过程 封装 pc 端、h5 端登录统一处理 封装页面模型和组件模型 封装上传组件、日期组件、select 组件等的统一操作方法 封装 input、click、hover、tap、scrollTo、hover、isElementShow、isElementExist、getElementVariable 等方法 提供根据 “html 标签>>页面文字” 形式获取页面元素及操作方法的统一支持 封装 baseTest,增加用例开始、结束后的统一操作 封装 assert,增加断言日志记录 业务用例 安装基础库 编排业务用例 3、执行逻辑 分环境执行 增加预上线环境代码变更触发、线上环境自动执行 监控源码变更 增加 gitlab webhook,监控开发源码合并 master 时自动在预上线环境执行 增加 gitlab webhook,监控测试用例变更时自动在生产环境执行 每日定时执行 增加 crontab,每日定时执行线上环境 [图片] [图片] [图片] [图片] 二、接口测试 接口测试主要针对于 Node 的 server 层,根据我们的开发规范,Node 不做复杂的业务逻辑,但是需要将服务化应用提供 dubbo 接口进行一次转换,或将多个 dubbo 接口组合起来,提供一个可供 h5/小程序渲染数据的 http 接口,转化过程就带来了各种数据的获取、组合、转换,形成了新的端到端接口。这个时候单单靠服务化接口的自动化已经不能保障对上层接口的全覆盖,所以我们针对 Node 接口也进行自动化测试。为了使用测试内部统一的测试框架,我们通过 java 去请求 Node 提供的 http 接口,那么当用例都写好之后,该如何评判接口测试的质量?是否完全覆盖了全部业务逻辑呢?此时就需要一个行之有效的方法来获取到测试的覆盖情况,以检查有哪些场景是接口测试中未覆盖的,做到更好的查漏补缺。 – istanbul[4] 是业界比较易用的 js 覆盖率工具,它利用模块加载的钩子计算语句、行、方法和分支覆盖率,以便在执行测试用例时透明的增加覆盖率。它支持所有类型的 js 覆盖率,包括单元测试、服务端功能测试以及浏览器测试。 但是,我们的接口用例写在 Java 代码中,通过 Http 请求的方式到达 Node 服务器,非 js 单测,也非浏览器功能测试,如何才能获取到 Node 接口的覆盖率呢? 解决办法是增加 cover 参数:–handle-sigint,通过增加 --handle-sigint 参数启动服务,当服务接收到一个 SIGINT 信号(linux 中 SIGINT 关联了 Ctrl+C),会通知 istanbul 生成覆盖率。这个命令非常适合我们,并且因此形成了我们接口覆盖率的一个模型: [代码]1. istanbule --handle-sigint 启动服务 2. 执行测试用例 3. 发送 SIGINT结束istanbule,得到覆盖率 [代码] 最终,解决了我们的 Node 接口覆盖率问题,并通过 jenkins 持续集成来自动构建 [图片] [图片] [图片] 当然,在获取覆盖率的时候有需求文件是不需要统计的,可以通过在根路径下增加 .istanbule.yml 文件的方式,来排除或者指定需要统计覆盖率的文件 [代码]verbose: false instrumentation: root: . extensions: - .js default-excludes: true excludes:['**/common/**','**/app/constants/**','**/lib/**'] embed-source: false variable: __coverage__ compact: true preserve-comments: false complete-copy: false save-baseline: false baseline-file: ./coverage/coverage-baseline.json include-all-sources: false include-pid: false es-modules: false reporting: print: summary reports: - lcov dir: ./coverage watermarks: statements: [50, 80] lines: [50, 80] functions: [50, 80] branches: [50, 80] report-config: clover: {file: clover.xml} cobertura: {file: cobertura-coverage.xml} json: {file: coverage-final.json} json-summary: {file: coverage-summary.json} lcovonly: {file: lcov.info} teamcity: {file: null, blockName: Code Coverage Summary} text: {file: null, maxCols: 0} text-lcov: {file: lcov.info} text-summary: {file: null} hooks: hook-run-in-context: false post-require-hook: null handle-sigint: false check: global: statements: 0 lines: 0 branches: 0 functions: 0 excludes: [] each: statements: 0 lines: 0 branches: 0 functions: 0 excludes: [] [代码] 三、单元测试 单元测试在测试分层中处于金字塔最底层的位置,单元测试做的比较到位的情况下,能过滤掉大部分的问题,并且提早发现 bug,也可以降低 bug 成本。推行一段时间的单测后发现,在有赞的 Node 框架中,业务层的 server 端只做接口组装,client 端面向浏览器,都不太适合做单元测试,所以我们只针对基础框架和通用组件进行单测,保障基础服务可以通过单测排除大部分的问题。比如基础框架中店铺通用信息服务,单测检查店铺信息获取;比如页面级商品组件,单测检查商品组件渲染的 html 是否和原来一致。 单测方案试行了两个框架: Jest[5] ava[6] 比较推荐的是 Jest 方案,它支持 Matchers 方式断言;支持 Snapshot Testing,可测试组件类代码渲染的 html 是否正确;支持多种 mock,包括 mock 方法实现、mock 定时器、mock 依赖的 module 等;支持 istanbule,可以方便的获取覆盖率。 总之,前端的单测方案也越来越成熟,需要前端开发人员更加关注 js 单测,将 bug 扼杀在摇篮中。 四、基础库变更报警 上面我们已经对基础服务和基础组件进行了单元测试,但是单测也不能完全保证基础库的变更完全没有问题,伴随着业务层引入新版本的基础库,bug 会进一步带入到业务层,最终影响 C 端用户的正常使用。那如何保障每次业务层引入新版本的基础库之后能做到全面的回归?如何让业务测试同学对基础库变更更加敏感呢?针对这种情况,我们着手做了一个基础库版本变更的小工具。实现思路如下: [代码]1. 对比一次 master 代码的提交或 merge 请求,判断 package.json 中是否有特定基础库版本变更 2. 将对应基础库的前后两个版本的代码对比发送到测试负责人 3. 根据 changelog 判断此次回归的用例范围 4. 增加 gitlab webhook,只有合并到合并发布分支或者 master 分支的代码才触发检查 [代码] 这个小工具的引入能及时通知测试人员针对什么需求改动了基础组件,以及这次基础组件的升级主要影响了哪些方面,这样能避免相对黑盒的测试。 第一版实现了最简功能,后续再深挖需求,可以做到前端代码变更的精准测试。 [图片] 五、sentry 报警 在刚接触前端测试的时候,js 的报错没有任何追踪,对于排查问题和定位问题有很大困扰。因此我们着手引入了 sentry 报警监控,用于监控线上环境 js 的运行情况。 – sentry[7] 是一款开源的错误追踪工具,它可以帮助开发者实时监控和修复崩溃。 开始我们接入的方式比较简单粗暴,直接全局接入,带来的问题是报警信息非常庞大,全局上报后 info、warn 信息都会打出来。 更改后,使用 sentry 的姿势是: sentry 的全局信息上报,并进行筛选 错误类型: TypeError 或者 ReferenceError 错误出现用户 > 1k 错误出现在 js 文件中 出现错误的店铺 > 2家 增加核心业务异常流程的主动上报 最终将筛选后的错误信息通过邮件的形式发送给告警接收人,在固定的时间集中修复。 [图片] [图片] 六、业务报警 除了 sentry 监控报警,Node 接口层的业务报警同样是必不可少的一部分,它能及时发现 Node 提供的接口中存在的业务异常。这部分是开发和运维同学做的,包括在 Node 框架底层接入日志系统;在业务层正确的上报错误级别、错误内容、错误堆栈信息;在日志系统增加合理的告警策略,超过阈值之后短信、电话告警,以便于及时发现问题、排查问题。 业务告警是最能快速反应生产环境问题的一环,如果某次发布之后发生告警,我们第一时间选择回滚,以保证线上的稳定性。 七、约定规范 除了上述的一些测试和告警手段之外,我们也做了一些流程规范、用例维护等基础建设,包括: 发布规范 多个日常分支合并发布 限制发布时间 规范发布流程 整理自测核心检查要点 基线用例库 不同业务 P0 核心用例定期更新 项目用例定期更新到业务回归用例库 线上问题场景及时更新到回归用例库 目前有赞的前端测试套路基本就是这样,当然有些平时的努力没有完全展开,例如接口测试中增加返回值结构体对比;增加线上接口或页面的拨测[8];给开发进行自测用例设计培训等等。也还有很多新功能探索中,如接入流量对比引擎,将线上流量导到预上线环境,在代码上线前进行对比测试;增加UI自动化的截图对比;探索小程序的UI自动化等等。 参考链接 [1] https://github.com/GoogleChrome/puppeteer [2] https://www.npmjs.com/package/mocha [3] https://www.npmjs.com/package/mochawesome [4] https://github.com/gotwarlost/istanbul [5] https://github.com/facebook/jest [6] https://github.com/avajs/ava [7] https://docs.sentry.io [8] https://tech.youzan.com/youzan-online-active-testing/
2019-04-25 - 小程序多端框架全面测评
最近前端届多端框架频出,相信很多有代码多端运行需求的开发者都会产生一些疑惑:这些框架都有什么优缺点?到底应该用哪个? 作为 Taro 开发团队一员,笔者想在本文尽量站在一个客观公正的角度去评价各个框架的选型和优劣。但宥于利益相关,本文的观点很可能是带有偏向性的,大家可以带着批判的眼光去看待,权当抛砖引玉。 那么,当我们在讨论多端框架时,我们在谈论什么: 多端 笔者以为,现在流行的多端框架可以大致分为三类: 1. 全包型 这类框架最大的特点就是从底层的渲染引擎、布局引擎,到中层的 DSL,再到上层的框架全部由自己开发,代表框架是 Qt 和 Flutter。这类框架优点非常明显:性能(的上限)高;各平台渲染结果一致。缺点也非常明显:需要完全重新学习 DSL(QML/Dart),以及难以适配中国特色的端:小程序。 这类框架是最原始也是最纯正的的多端开发框架,由于底层到上层每个环节都掌握在自己手里,也能最大可能地去保证开发和跨端体验一致。但它们的框架研发成本巨大,渲染引擎、布局引擎、DSL、上层框架每个部分都需要大量人力开发维护。 2. Web 技术型 这类框架把 Web 技术(JavaScript,CSS)带到移动开发中,自研布局引擎处理 CSS,使用 JavaScript 写业务逻辑,使用流行的前端框架作为 DSL,各端分别使用各自的原生组件渲染。代表框架是 React Native 和 Weex,这样做的优点有: 开发迅速 复用前端生态 易于学习上手,不管前端后端移动端,多多少少都会一点 JS、CSS 缺点有: 交互复杂时难以写出高性能的代码,这类框架的设计就必然导致 [代码]JS[代码] 和 [代码]Native[代码] 之间需要通信,类似于手势操作这样频繁地触发通信就很可能使得 UI 无法在 16ms 内及时绘制。React Native 有一些声明式的组件可以避免这个问题,但声明式的写法很难满足复杂交互的需求。 由于没有渲染引擎,使用各端的原生组件渲染,相同代码渲染的一致性没有第一种高。 3. JavaScript 编译型 这类框架就是我们这篇文章的主角们:[代码]Taro[代码]、[代码]WePY[代码] 、[代码]uni-app[代码] 、 [代码]mpvue[代码] 、 [代码]chameleon[代码],它们的原理也都大同小异:先以 JavaScript 作为基础选定一个 DSL 框架,以这个 DSL 框架为标准在各端分别编译为不同的代码,各端分别有一个运行时框架或兼容组件库保证代码正确运行。 这类框架最大优点和创造的最大原因就是小程序,因为第一第二种框架其实除了可以跨系统平台之外,也都能编译运行在浏览器中。(Qt 有 Qt for WebAssembly, Flutter 有 Hummingbird,React Native 有 [代码]react-native-web[代码], Weex 原生支持) 另外一个优点是在移动端一般会编译到 React Native/Weex,所以它们也都拥有 Web 技术型框架的优点。这看起来很美好,但实际上 React Native/Weex 的缺点编译型框架也无法避免。除此之外,编译型框架的抽象也不是免费的:当 bug 出现时,问题的根源可能出在运行时、编译时、组件库以及三者依赖的库等等各个方面。在 Taro 开源的过程中,我们就遇到过 Babel 的 bug,React Native 的 bug,JavaScript 引擎的 bug,当然也少不了 Taro 本身的 bug。相信其它原理相同的框架也无法避免这一问题。 但这并不意味着这类为了小程序而设计的多端框架就都不堪大用。首先现在各巨头超级 App 的小程序百花齐放,框架会为了抹平小程序做了许多工作,这些工作在大部分情况下是不需要开发者关心的。其次是许多业务类型并不需要复杂的逻辑和交互,没那么容易触发到框架底层依赖的 bug。 那么当你的业务适合选择编译型框架时,在笔者看来首先要考虑的就是选择 DSL 的起点。因为有多端需求业务通常都希望能快速开发,一个能够快速适应团队开发节奏的 DSL 就至关重要。不管是 React 还是 Vue(或者类 Vue)都有它们的优缺点,大家可以根据团队技术栈和偏好自行选择。 如果不管什么 DSL 都能接受,那就可以进入下一个环节: 生态 以下内容均以各框架现在(2019 年 3 月 11日)已发布稳定版为标准进行讨论。 开发工具 就开发工具而言 [代码]uni-app[代码] 应该是一骑绝尘,它的文档内容最为翔实丰富,还自带了 IDE 图形化开发工具,鼠标点点点就能编译测试发布。 其它的框架都是使用 CLI 命令行工具,但值得注意的是 [代码]chameleon[代码] 有独立的语法检查工具,[代码]Taro[代码] 则单独写了 ESLint 规则和规则集。 在语法支持方面,[代码]mpvue[代码]、[代码]uni-app[代码]、[代码]Taro[代码] 、[代码]WePY[代码] 均支持 TypeScript,四者也都能通过 [代码]typing[代码] 实现编辑器自动补全。除了 API 补全之外,得益于 TypeScript 对于 JSX 的良好支持,Taro 也能对组件进行自动补全。 CSS 方面,所有框架均支持 [代码]SASS[代码]、[代码]LESS[代码]、[代码]Stylus[代码],Taro 则多一个 [代码]CSS Modules[代码] 的支持。 所以这一轮比拼的结果应该是: [代码]uni-app[代码] > [代码]Taro[代码] > [代码]chameleon[代码] > [代码]WePY[代码]、[代码]mpvue[代码] [图片] 多端支持度 只从支持端的数量来看,[代码]Taro[代码] 和 [代码]uni-app[代码] 以六端略微领先(移动端、H5、微信小程序、百度小程序、支付宝小程序、头条小程序),[代码]chameleon[代码] 少了头条小程序紧随其后。 但值得一提的是 [代码]chameleon[代码] 有一套自研多态协议,编写多端代码的体验会好许多,可以说是一个能戳到多端开发痛点的功能。[代码]uni-app[代码] 则有一套独立的条件编译语法,这套语法能同时作用于 [代码]js[代码]、样式和模板文件。[代码]Taro[代码] 可以在业务逻辑中根据环境变量使用条件编译,也可以直接使用条件编译文件(类似 React Native 的方式)。 在移动端方面,[代码]uni-app[代码] 基于 [代码]weex[代码] 定制了一套 [代码]nvue[代码] 方案 弥补 [代码]weex[代码] API 的不足;[代码]Taro[代码] 则是暂时基于 [代码]expo[代码] 达到同样的效果;[代码]chameleon[代码] 在移动端则有一套 SDK 配合多端协议与原生语言通信。 H5 方面,[代码]chameleon[代码] 同样是由多态协议实现支持,[代码]uni-app[代码] 和 [代码]Taro[代码] 则是都在 H5 实现了一套兼容的组件库和 API。 [代码]mpvue[代码] 和 [代码]WePY[代码] 都提供了转换各端小程序的功能,但都没有 h5 和移动端的支持。 所以最后一轮对比的结果是: [代码]chameleon[代码] > [代码]Taro[代码]、[代码]uni-app[代码] > [代码]mpvue[代码]、[代码]WePY[代码] [图片] 组件库/工具库/demo 作为开源时间最长的框架,[代码]WePY[代码] 不管从 Demo,组件库数量 ,工具库来看都占有一定优势。 [代码]uni-app[代码] 则有自己的插件市场和 UI 库,如果算上收费的框架和插件比起 [代码]WePy[代码] 也是完全不遑多让的。 [代码]Taro[代码] 也有官方维护的跨端 UI 库 [代码]taro-ui[代码] ,另外在状态管理工具上也有非常丰富的选择(Redux、MobX、dva),但 demo 的数量不如前两个。但 [代码]Taro[代码] 有一个转换微信小程序代码为 Taro 代码的工具,可以弥补这一问题。 而 [代码]mpvue[代码] 没有官方维护的 UI 库,[代码]chameleon[代码] 第三方的 demo 和工具库也还基本没有。 所以这轮的排序是: [代码]WePY[代码] > [代码]uni-app[代码] 、[代码]taro[代码] > [代码]mpvue[代码] > [代码]chameleon[代码] [图片] 接入成本 接入成本有两个方面: 第一是框架接入原有微信小程序生态。由于目前微信小程序已呈一家独大之势,开源的组件和库(例如 [代码]wxparse[代码]、[代码]echart[代码]、[代码]zan-ui[代码] 等)多是基于原生微信小程序框架语法写成的。目前看来 [代码]uni-app[代码] 、[代码]Taro[代码]、[代码]mpvue[代码] 均有文档或 demo 在框架中直接使用原生小程序组件/库,[代码]WePY[代码] 由于运行机制的问题,很多情况需要小改一下目标库的源码,[代码]chameleon[代码] 则是提供了一个按步骤大改目标库源码的迁移方式。 第二是原有微信小程序项目部分接入框架重构。在这个方面 Taro 在京东购物小程序上进行了大胆的实践,具体可以查看文章《Taro 在京东购物小程序上的实践》。其它框架则没有提到相关内容。 而对于两种接入方式 Taro 都提供了 [代码]taro convert[代码] 功能,既可以将原有微信小程序项目转换为 Taro 多端代码,也可以将微信小程序生态的组件转换为 Taro 组件。 所以这轮的排序是: [代码]Taro[代码] > [代码]mpvue[代码] 、 [代码]uni-app[代码] > [代码]WePY[代码] > [代码]chameleon[代码] 流行度 从 GitHub 的 star 来看,[代码]mpvue[代码] 、[代码]Taro[代码]、[代码]WePY[代码] 的差距非常小。从 NPM 和 CNPM 的 CLI 工具下载量来看,是 Taro(3k/week)> mpvue (2k/w) > WePY (1k/w)。但发布时间也刚好反过来。笔者估计三家的流行程度和案例都差不太多。 [代码]uni-app[代码] 则号称有上万案例,但不像其它框架一样有一些大厂应用案例。另外从开发者的数量来看也是 [代码]uni-app[代码] 领先,它拥有 20+ 个 QQ 交流群(最大人数 2000)。 所以从流行程度来看应该是: [代码]uni-app[代码] > [代码]Taro[代码]、[代码]WePY[代码]、[代码]mpvue[代码] > [代码]chameleon[代码] [图片] 开源建设 一个开源作品能走多远是由框架维护团队和第三方开发者共同决定的。虽然开源建设不能具体地量化,但依然是衡量一个框架/库生命力的非常重要的标准。 从第三方贡献者数量来看,[代码]Taro[代码] 在这一方面领先,并且 [代码]Taro[代码] 的一些核心包/功能(MobX、CSS Modules、alias)也是由第三方开发者贡献的。除此之外,腾讯开源的 [代码]omi[代码] 框架小程序部分也是基于 Taro 完成的。 [代码]WePY[代码] 在腾讯开源计划的加持下在这一方面也有不错的表现;[代码]mpvue[代码] 由于停滞开发了很久就比较落后了;可能是产品策略的原因,[代码]uni-app[代码] 在开源建设上并不热心,甚至有些部分代码都没有开源;[代码]chameleon[代码] 刚刚开源不久,但它的代码和测试用例都非常规范,以后或许会有不错的表现。 那么这一轮的对比结果是: [代码]Taro[代码] > [代码]WePY[代码] > [代码]mpvue[代码] > [代码]chameleon[代码] > [代码]uni-app[代码] 最后补一个总的生态对比图表: [图片] 未来 从各框架已经公布的规划来看: [代码]WePY[代码] 已经发布了 [代码]v2.0.alpha[代码] 版本,虽然没有公开的文档可以查阅到 [代码]2.0[代码] 版本有什么新功能/特性,但据其作者介绍,[代码]WePY 2.0[代码] 会放大招,是一个「对得起开发者」的版本。笔者也非常期待 2.0 正式发布后 [代码]WePY[代码] 的表现。 [代码]mpvue[代码] 已经发布了 [代码]2.0[代码] 的版本,主要是更新了其它端小程序的支持。但从代码提交, issue 的回复/解决率来看,[代码]mpvue[代码] 要想在未来有作为首先要打消社区对于 [代码]mpvue[代码] 不管不顾不更新的质疑。 [代码]uni-app[代码] 已经在生态上建设得很好了,应该会在此基础之上继续稳步发展。如果 [代码]uni-app[代码] 能加强开源开放,再加强与大厂的合作,相信未来还能更上一层楼。 [代码]chameleon[代码] 的规划比较宏大,虽然是最后发的框架,但已经在规划或正在实现的功能有: 快应用和端拓展协议 通用组件库和垂直类组件库 面向研发的图形化开发工具 面向非研发的图形化页面搭建工具 如果 [代码]chameleon[代码] 把这些功能都做出来的话,再继续完善生态,争取更多第三方开发者,那么在未来 [代码]chameleon[代码] 将大有可为。 [代码]Taro[代码] 的未来也一样值得憧憬。Taro 即将要发布的 [代码]1.3[代码] 版本就会支持以下功能: 快应用支持 Taro Doctor,自动化检查项目配置和代码合法性 更多的 JSX 语法支持,1.3 之后限制生产力的语法只有 [代码]只能用 map 创造循环组件[代码] 一条 H5 打包体积大幅精简 同时 [代码]Taro[代码] 也正在对移动端进行大规模重构;开发图形化开发工具;开发组件/物料平台以及图形化页面搭建工具。 结语 那说了那么多,到底用哪个呢? 如果不介意尝鲜和学习 DSL 的话,完全可以尝试 [代码]WePY[代码] 2.0 和 [代码]chameleon[代码] ,一个是酝酿了很久的 2.0 全新升级,一个有专门针对多端开发的多态协议。 [代码]uni-app[代码] 和 [代码]Taro[代码] 相比起来就更像是「水桶型」框架,从工具、UI 库,开发体验、多端支持等各方面来看都没有明显的短板。而 [代码]mpvue[代码] 由于开发一度停滞,现在看来各个方面都不如在小程序端基于它的 [代码]uni-app[代码] 。 当然,Talk is cheap。如果对这个话题有更多兴趣的同学可以去 GitHub 另行研究,有空看代码,没空看提交: chameleon: https://github.com/didi/chameleon mpvue: https://github.com/Meituan-Dianping/mpvue Taro: https://github.com/NervJS/taro uni-app: https://github.com/dcloudio/uni-app WePY: https://github.com/Tencent/wepy (按字母顺序排序)
2019-03-19 - 【优化】利用函数防抖和函数节流提高小程序性能
大家好,上次给大家分享了swiper仿tab的小技巧: https://developers.weixin.qq.com/community/develop/doc/000cc0b94ac5f8dcf4e7666475b804 今天给大家分享两个有用的函数,《函数防抖和函数节流》 函数防抖和函数节流是都优化高频率执行js代码的一种手段,因为是js实现的,所以在小程序里也是适用的。 首先先来理解一下两者的概念和区别: 函数防抖(debounce)是指事件在一定时间内事件只执行一次,如果在这段时间又触发了事件,则重新开始计时,打个很简单的比喻,比如在打王者荣耀时,一定要连续干掉五个人才能触发hetai kill '五连绝世'效果,如果中途被打断就得重新开始连续干五个人了。 函数节流(throttle)是指限制某段时间内事件只能执行一次,比如说我要求自己一天只能打一局王者荣耀。 这里也有个可视化工具可以让大家看一下三者的区别,分别是正常情况下,用了函数防抖和函数节流的情况下:http://demo.nimius.net/debounce_throttle/ 适用场景: 函数防抖 搜索框搜索联想。只需用户最后一次输入完,再发送请求 手机号、邮箱验证输入检测 窗口resize。只需窗口调整完成后,计算窗口大小。防止重复渲染 高频点击提交,表单重复提交 函数节流 滚动加载,加载更多或滚到底部监听 搜索联想功能 实现原理 函数防抖 [代码]const _.debounce = (func, wait) => {[代码][代码] [代码][代码]let timer;[代码] [代码] [代码][代码]return[代码] [代码]() => {[代码][代码] [代码][代码]clearTimeout(timer);[代码][代码] [代码][代码]timer = setTimeout(func, wait);[代码][代码] [代码][代码]};[代码][代码]};[代码] 函数节流 [代码]const throttle = (func, wait) => {[代码][代码] [代码][代码]let last = 0;[代码][代码] [代码][代码]return[代码] [代码]() => {[代码][代码] [代码][代码]const current_time = +[代码][代码]new[代码] [代码]Date();[代码][代码] [代码][代码]if[代码] [代码](current_time - last > wait) {[代码][代码] [代码][代码]func.apply([代码][代码]this[代码][代码], arguments);[代码][代码] [代码][代码]last = +[代码][代码]new[代码] [代码]Date();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]};[代码][代码]};[代码] 上面两个方法都是比较常见的,算是简化版的函数 lodash中的 Debounce 、Throttle lodash中已经帮我们封装好了这两个函数了,我们可以把它引入到小程序项目了,不用全部引入,只需要引入debounce.js和throttle.js就行了,链接:https://github.com/lodash/lodash 使用方法可以看这个代码片段,具体的用法可以看上面github的文档,有很详细的介绍:https://developers.weixin.qq.com/s/vjutZpmL7A51 系甘先,得闲饮茶
2019-01-14