最近的工做重心一直在小程序,也开发了几个小程序,对小程序开发的流程及相关技术相对比较熟悉,在开发过程当中也总结了一些心得经验、了解一些小程序文档上没有的东西、踩了一些坑。因此想着写篇文章记录下来,并借此将小程序开发的相关知识进行梳理,方便之后参考,也做为本身工做的阶段性总结。同时也但愿能够经过文章,结识更多朋友,多交流,互相学习,共同进步。另文章如有不对之处,还望指出与不吝赐教。javascript
微信小程序开发,入门算是很是简单,只要看官文文档便可小程序简易教程。如何申请小程序帐号,如何开发本身第一个小程序,如何发布,这一系列hello world操做官方文档都有手把手教学。小程序开发的每一个步骤,提供的能力文档里都有,我的以为,作小程序开发,有事没事都看下文档,由于小程序更新比较快速,同时一些细小的能力咱们可能会漏掉,因此多看文档。html
先来看看小程序项目的文件目录结构前端
除了app.json必须位于根目录下,其余文件随意,而且均可以删。而且页面文件能够放到如何位置,只要在app.json中的pages中配置了就能够。能够说是很灵活。你还能够多个页面放在同个文件夹下(我相信你不会这样作的,何须糟蹋本身呢)。 java
接下来简单介绍下各个文件:android
对于一个小程序项目而言,最重要的文件是app.json,它也是开发工具识别一个文件夹是否为小程序项目的标识。当使用开发者工具建立一个项目是,若是选择的是空文件夹,它会建立一个新的项目。若是是一个有文件的文件夹,它会看该文件夹中是否有app.jon文件,若是有,则它会认为是一个小程序项目,则会打开该项目,若是文件夹中没有app.json文件,则提示没法建立项目。ios
app.json必须放置于项目的根目录下,它是小程序项目的全局配置文件。在小程序代码包准备完成进行启动后(下文会详细介绍小程序从用户点击打开小程序到小程序销毁的整个过程),会先读取app.json文件,进行小程序的初试化,好比初始化整个小程序外框样式,获取首页页面地址等。web
其实小程序就是微信提供的一个容器,各个页面就在这个容器里加载运行销毁json
下面介绍下小程序的全局配置选项:canvas
注意:小程序
- 全部配置项key必须使用双引号括起来,value值为字符串类型的也必须使用双引号,不支持单引号
- 由于小程序功能迭代很是迅速,基础库版本更新也很快,因此下面的介绍是截止目前的最新版本库2.4.0
"pages": [
"pages/index/index",
"pages/log/log"
]
复制代码
在app.json中,pages选项是必须配置的。该配置项注册了小程序全部页面的地址,其中每一项都是页面的 路径+文件名 。配置的字符串其实就是每一个页面wxml路径,去掉.wxml后缀。由于框架会自动去寻找路径下.json、.js、.wxml、.wxss四个文件进行整合。也就意味着.json、.js、.wxss这三个文件的文件名必需要和.wxml的一致,不然不生效。因此一个页面至少必须得有.wxml文件。
总结:
- 页面的.json、.js、.wxss文件必须与.wxml文件同名,不然不生效
- 每一个页面都必须pages下注册,没有注册的页面,若是不访问,编译能经过,一旦试图访问该页面则会报错
- 能够经过在pages下添加一个选项快速新建一个页面,开发工具会自动生成对应的文件
"window":{
"enablePullDownRefresh": ture,
"navigationStyle": "custom"
}
复制代码
该配置项用于配置小程序的全局外观样式,具体请查阅文档。这里重点提一下两个比较实用的
//去掉默认的导航栏,轻松实现全面屏
"navigationStyle": "custom" ,
//开启自带的下拉刷新,减小本身写样式
"enablePullDownRefresh": ture,
复制代码
该选项可让咱们轻松实现导航栏tab效果,不过有个不足就是跳转可操做性很是低。就是每一个tab只能跳当前小程序页面,不一样跳到其余小程序。若是须要跳到其余小程序,还需本身封装个组件。
这是网络请求超时时间,能够设置不一样类型请求的超时时间,好比wx.request、wx.uploadFile等。其实不少时候咱们都会忽略这个选项,小程序默认是60s超时,但咱们应该手动设置更低的值,由于咱们的接口通常都会在10s内完成请求(若是超过10s,那你是时候优化了),因此若是网络或者服务器出问题了,那么会让用户等60s,最后仍是失败,这对用户很不友好,还不如提早告诉用户,如今出问题了,请稍后再试。
前段时间因为公司服务器网关出现了点小问题,致使有些请求链接不上,出现大量链接超时。经过以前添加的错误信息收集插件(这个是性能优化,下文有讲到)看到了不少接口返回time-out 60s。让用户等了60s仍是失败,这不友好。因此这个超时时间通常设置15s-30s比较好。
是否开启debug功能,开启后查看更多的调试信息,方便定位问题,开发阶段能够考虑开启
这个是结合插件使用的,由于微信小程序插件有很大限制,插件里提供的api颇有限,wx.login 和 wx.requestPayment 在插件中不能使用,若是须要获取用户信息和进行支付,就必须经过插件提供的功能也实现。当你的小程序下的插件启用了插件功能也时,必须设置该选项为true
小程序插件必须挂载在一个微信小程序中,一个小程序也只能开通一个插件。当你小程序开通的插件启用了插件功能也时,必须设置该选项为true
"plugins": {
"myPlugin": {
"version": "1.0.0",
"provider": "wxidxxxxxxxxxxxxxxxx"
}
}
复制代码
当小程序使用了插件就必须在这里声明引入。小程序自身开通的小程序不能在自己应用
"navigateToMiniProgramAppIdList": [
"wxe5f52902cf4de896"
]
复制代码
以前小程序之间只要是关联了经过公众号就能够相互跳转,现在微信作出了限制,要这个这里配置好须要跳转的小程序,上限为10个,还必须写死,不支持配置。因此当小程序有跳转到其余小程序,必定要配好这个,不然没法跳转。
"usingComponents": {
"hello-component": "plugin://myPlugin/hello-component"
}
复制代码
使用自定义组件或者插件提供的组件前,必须先在这里声明
下面来讲说小程序从用户点击打开到销毁的整个过程。用图说话更清晰,特意画了个流程图:
小程序启动会有两种状况,一种是「冷启动」,一种是「热启动」。 假如用户已经打开过某小程序,而后在必定时间内再次打开该小程序,此时无需从新启动,只需将后台态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的状况,此时小程序须要从新加载启动。
上面的流程图包含了全部内容,但毕竟文字有限,接下来详细说下几个点。
if (wx.canIUse('getUpdateManager')) {
//检测是否有版本更新
var updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调,有更新
if (res.hasUpdate) {
wx.showLoading({
title: '检测到新版本',
})
}
})
updateManager.onUpdateReady(function () {
wx.hideLoading();
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: function (res) {
if (res.confirm) {
//清楚本地缓存
try {
wx.clearStorageSync()
} catch (e) {
// Do something when catch error
}
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
// 新的版本下载失败
console.log('新版本下载失败');
})
}
复制代码
对于小程序开发工具,尚未一款让开发者满意的工具,至少我不满意,哈哈哈!微信提供的微信开发者工具。除了编译器不行外,其余都还行。但因为开发工具、ios、android三个平台运行小程序的内核不一样。因此有时会出现开发工具上没问题,真机有问题的状况,特别是样式,能够经过在开发工具中设置上传代码时样式自动补全来解决大多数问题。另外微信开发者工具提供了真机调试功能,该功能对真机调试很是方便
还有就是能够自定义编译条件
服务器域名request合法域名每月只能修改5次。因此不该该每次请求一个新域名就添加一次。在开发阶段,在微信开发者工具上勾上不校验合法域名,真机上须要开启调试模式,就能够先不配置合法域名的状况下请求任何域名甚至ip地址。待开发完成了,再一次性配置全部合法域名,在微信开发者工具上取消不校验合法域名,真机上关闭调试模式,而后开始测试。
使用体验版+线上环境的接口,这就是和线上环境如出一辙的,因此在发布前,使用体验版+线上环境过一遍。若是没问题,发布之后也就没问题了。
小程序二维码只要发布了线上版本调用生成小程序二维码接口才能成功返回二维码。并且二维码识别是线上版本,因此还未发布的小程序是没法生成二维码的。
线上版本有个版本回退功能,这里有个坑,就是版本回退之后,退回的版本须要从新审核才能发布
还有设置体验版时能够设置指定路径和参数,这样很方便测试
接下来讲说使用频率比较多,功能强大,但又有比较多坑的几个组件
web-view的出现,让小程序和H5网页以前的跳转成为了可能。经过把H5页面放置到web-view中,可让H5页面在小程序内运行。同时在H5页面中也能够跳转回小程序页面。能够说是带来了很大的便利,但同时因为web-view的诸多限制,用起来也不是很舒服。
- 须要打开的H5页面必须在后台业务页面中配置,这其中还有个服务校验。另外H5页面必须是https协议,不然没法打开
- web-view中没法在页面中调起分享,若是须要分享,好比跳回小程序原生页面
- 小程序与web-view里H5通讯问题。小程序向web-view传递,不敏感信息能够经过页面url传递。若是是敏感信息好比用户token等,可让服务端重定向,好比请求服务端一个地址,让他把敏感信息写在cookie中,再重定向到咱们的H5页面。以后H5页面就能够经过在cookie中拿这些敏感数据了,或者http-only,发送请求时直接带上。
- 每次web-view中src值有变化就会从新加载一次页面。因此个src拼接参数时,须要先赋值给个变量拼接好再一次性setData给web-view的src,防止页面重复刷新
- 从微信客户端6.7.2版本开始,
navigationStyle: custom
对组件无效。也就意味着使用web-view时,自带的导航栏没法去掉。- 由于导航栏没法去掉,这里就出现了一个巨大的坑。实现全屏效果问题。若是想要实现H5页面全屏,就是不滑动,全屏显示完全部内容。这时若是你使用
width:100%;height:100%
,你会发现,你页面底部可能会缺失一段。上图:
由于web-view是默认铺满全屏的,也就是web-view宽高和屏幕宽高同样。而后H5页面这是高度100%,这是相对web-view的高度,也是屏幕高度。可是关键问题:web-view里H5页面是从导航栏下开始渲染的。这就致使了H5页面溢出了屏幕,没法达到全屏效果。
解决方法
这个问题我在前段时间的实际项目碰到过,咱们要作个H5游戏,要求是全屏,刚开始我也是设置高度100%。后来发现底部一块不见了。个人解决方法比较粗暴,若是有更好的解决方法,欢迎评论交流。 个人解决方法是:经过拼接宽高参数在H5页面url上,这个宽高是在web-view外层计算好的。H5页面直接读取url上的宽高,动态设置页面的宽高。页面高度的计算,根据上图,很显然就是屏幕高度减去导航栏高度。宽度都是同样的,直接是屏幕宽度。
但问题又来了,貌似没有途径获取导航栏高度。并且对于不一样机型的手机,导航栏高度不一样。通过了对多个机型导航栏跟屏幕高度的比较。发现了一个规律,导航栏高度与屏幕高度、屏幕宽高比有必定的关系。因此根据多个机型就计算出了这个比例。这解决了95%以上手机的适配问题,只有少数机型适配不是很好。到基本实现了全屏效果。具体代码以下:
onLoad (options) {
//同步获取屏幕信息,如今用到的是屏幕宽高
var res = wx.getSystemInfoSync();
if (res) {
var widHeight = res.screenHeight;
//对于大多数手机,屏幕高度/屏幕宽度 = 1.78。此时导航栏占屏幕高度比为0.875
var raito = 0.875;
if (res.screenHeight / res.screenWidth > 1.95) {
//对于全屏手机,这个占比会更高些
raito = 0.885;
} else if (res.screenHeight / res.screenWidth > 1.885) {
raito = 0.88;
}
//作兼容处理,只有微信版本库高于6.7.2,有导航栏才去兼容,不然能够直接使用高度100%。res.statusBarHeight是手机顶部状态栏高度
//若是微信版本号大于6.7.2,有导航栏
if (util.compareVersion(res.version, "6.7.2") > 0) {
widHeight = Math.round(widHeight * raito) + (res.statusBarHeight || 0);
}
this.setDate({
//将H5页面宽高拼接在url上,赋值给web-view的src便可加载出H5页面
webview_src: util.joinParams(h5_src, {
"height": widHeight,
"width": res.screenWidth
})
})
}
}
复制代码
当咱们要实现一个区域内滑动效果时,在H5页面中咱们设置overflow-y: scroll
便可。但在小程序中,没有该属性。须要用到scroll-view标签。具体操做实现咱们能够查看文件scroll-view。
锚点定位在前端开发中会常常用到,在H5页面中,咱们会在url后面加上#来实现锚点定位效果。可是在小程序中这样是不起做用的,由于小程序内渲染页面的容易不是一个浏览器,没法实时监听Hash值得变化。可是使用scroll-view,咱们能够实现锚点点位效果。主要是使用scroll-into-vie属性具体实现咱们直接上代码
scroll-into-view | String | 值应为某子元素id(id不能以数字开头)。设置哪一个方向可滚动,则在哪一个方向滚动到该元素
wxml文件
<!--toView的值动态变化,当toView为luckydraw时,会定位到id为luckydraw的view 须要注意的是,这里须要设置高度为屏幕高度-->
<scroll-view scroll-y scroll-into-view="{{toView}}" scroll-with-animation = "true" style="height: 100%; white-space:nowrap">
<view id="top"></view>
<view id="luckydraw"></view>
<view id="secskill"></view>
<scroll-view>
复制代码
画布标签,它是原生组件,因此它必须位于屏幕最上边,并且是不能隐藏的。因此若是想要使用canvas动态生成分享照片。那你要设置她的宽高和屏幕同样。要不导出为照片时就会失真。由于这个缘由,因此生成分享照片仍是有服务端实现吧,照片失真太严重了。
给用户发送消息对一个小程序是很是重要的,它能够召唤回用户,导量效果很是明显。咱们能够经过模板消息想小程序用户发送消息,但前提是咱们得获取到openid和formid。用户登陆咱们便可便可获取到用户openid。而只要用户有点击行为,咱们便可获取到formid获取formid。因此说formid是很重要的。咱们能够提早收集好formid,在须要的时候给用户推送消息。咱们能够个每一个button都包上form标签,只要有用户点击行为均可以收集到formid.
<form bindsubmit="formSubmit" report-submit='true'>
<button formType="submit">点击</button>
</form>
复制代码
咱们实现一个formid收集系统,为了尽可能减小冗余代码和减小对业务的影响,咱们的设计是这样的
formTpye=submit
的button有点击都能获取到formid。wxml文件
<!--在整个页面的最外层包裹form标签,这样就不一样对每一个button都包裹一个form标签,代码简洁-->
<form bindsubmit="formSubmit" report-submit='true'>
<view>页面内容</view>
<view>页面内容</view>
<button formType="submit">点击</button>
<view>页面内容</view>
<view>
<button formType="submit">点击</button>
</view>
</form>
复制代码
page.js文件
//每次用户有点击,都将formid添加到全局数组中
formSubmit(e) {
//须要实时发送的,不添加
if(e.target.dataset.sendMsg){
formid = e.detail.formId;
return;
}
app.appData.formIdArr.push(e.detail.formId);
}
复制代码
app.js
onHide: function () {
//小程序切到后台时上传formid
this.submitFormId();
},
复制代码
从用户打开小程序到小程序销毁,咱们能够想一想有哪些地方是能够优化的。首先是打开速度。小程序打开速度直接影响了用户留存。在小程序后台,运维中心-监控告警下有个加载性能监控数据,咱们能够看到小程序启动总耗时、下载耗时、首次渲染耗等加载相关的数据。而这里的打开速度其实就是小程序的启动总耗时。它包括了代码包下载、首次渲染,微信内环境初始化等步凑。在这一步,咱们能作的就是如何加快代码包下载速度和减小首次渲染时间
在小程序呈现给用户以后,接下来如何提升用户体验,加强小程序健壮性的问题了。每一个程序都有bug。只是咱们没发现而已,尽管在测试阶段,咱们进行了详尽的测试。可是在实际生产环境,不一样的用户环境,不一样的操做路径,随时会触发一些隐藏的bug。这时若是用户没有向咱们报告,咱们是没法获知的。因此有必要给咱们的小程序增长错误信息收集,js脚本错误,意味着整个程序挂掉了,没法响应用户操做。因此对于运行时的脚本错误,咱们应该上报。对出现的bug及时修复,加强程序健壮性,提供用户体验。
每一个程序都有大量的先后端数据交互,这是经过http请求进行的。所以,还有一个错误信息收集就是接口错误信息收集。对那些请求状态码非2XX、3XX的,或者请求接口成功了,可是数据不是咱们预期的,均可以进行信息采集。
经过对小程序运行时脚本和http请求进行监控,咱们就能够实时了解咱们线上小程序的运行情况,有什么问题能够及时发现,及时修复,极高地提升了用户体验性。
让小程序快,主要因素有两个,代码包下载和首屏渲染。 咱们来看一个数据:
前面状态小程序代码大小是650Kb左右,这是下载耗时(虽然跟用户网络有关,但这个是所有用户平均时间)是1.3s左右。可是通过优化,将代码包下降至200kb左右时。下载耗时只有0.6s左右。因此说,代码包减小500kb,下载耗时能减小0.5s。这个数据仍是很是明显和。因此说,在不影响业务逻辑的状况下,咱们小程序代码包应该尽量地小。那么如何下降代码包大小呢?如下有几点能够参考
接下来是首屏渲染,从上图的小程序生命周期能够看出,从加载首页代码带首页完成渲染,这段时间就是白屏时间,也就是首次渲染时间。而小程序在这段时间内,主要工做是:加载首页代码、建立View和AppService层、初试数据传输、页面渲染。在这四个步骤中,加载首页代码,前面已经说过;建立View和AppService层,是微信完成的,跟用户手机有关,这不是咱们可控的。咱们能作的就是减小初试数据传输时间和页面渲染时间。
Page({
//与页面渲染有关的数据放这里
data: {
goods_list:[]
},
//与页面渲染无关的数据放这里
_data: {
timer: null
}
})
复制代码
接下来就是给小程序增长错误信息收集,包括js脚本错误信息收集和http请求错误信息收集。前段时间,在时间工做开发中,为了更好的复用和管理,我把这个错误信息收集功能作成了插件。然而作成插件并无想象中的那么美好,下面再具说。
脚本错误收集
对于脚本错误收集,这个相对比较简单,由于在app.js中提供了监听错误的onError函数
只不过错误信息是包括堆栈等比较详细的错误信息,而后当上传时咱们并不须要这么信息,第一浪费宽带,第二看着累又无用。咱们须要的信息是:错误类型、错误信息描述、错误位置。
thirdScriptError
aa is not defined;at pages/index/index page test function
ReferenceError: aa is not defined
at e.test (http://127.0.0.1:62641/appservice/pages/index/index.js:17:3)
at e.<anonymous> (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:31500)
at e.a (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:26386)
at J (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:20800)
at Function.<anonymous> (http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:22389)
at http://127.0.0.1:62641/appservice/__dev__/WAService.js:16:27889
at http://127.0.0.1:62641/appservice/__dev__/WAService.js:6:16777
at e.(anonymous function) (http://127.0.0.1:62641/appservice/__dev__/WAService.js:4:3403)
at e (http://127.0.0.1:62641/appservice/appservice?t=1543326089806:1080:20291)
at r.registerCallback.t (http://127.0.0.1:62641/appservice/appservice?t=1543326089806:1080:20476)
复制代码
这是错误信息字符串,接下来咱们对它进行截取只须要拿咱们想要的信息便可。咱们发现这个字符串是有规则的。第一行是错误类型,第二行是错误详情和发生的位置,而且是";"分好分开。因此咱们仍是很容易就能够拿到咱们想要的信息。
//格式化错误信息
function formateErroMsg(errorMsg){
//包一层try catch 不要让信息收集影响了业务
try{
var detailMsg = '';
var detailPosition= '';
var arr = errorMsg.split('\n')
if (arr.length > 1) {
//错误详情和错误位置在第二行并用分好隔开
var detailArr = arr[1].split(';')
detailMsg = detailArr.length > 0 ? detailArr[0] : '';
if (detailArr.length > 1) {
detailArr.shift()
detailPosition = detailArr.join(';')
}
}
var obj = {
//错误类型就是第一行
error_type: arr.length > 0 ? arr[0] : '',
error_msg: detailMsg,
error_position: detailPosition
};
return obj
}catch(e){}
}
复制代码
获取到咱们想要的信息,就能够发送到咱们服务后台,进行数据整理和显示,这个须要服务端配合,就不深刻讲了,咱们拿到了数据,其余都不是事。
http请求错误信息收集 对于http请求错误信息收集方式,咱们尽可能不要暴力埋点,每一个请求发送前发送后加上咱们的埋点。这样工做量太大,也不易维护。所以,咱们能够从底层出发,拦截wx.request请求。使用Object.definePropert对wx对象的request进行从新定义。具体实现以下
function rewriteRequest(){
try {
const originRequest = wx.request;
Object.defineProperty(wx, 'request', {
configurable:true,
enumerable: true,
writable: true,
value: function(){
let options = arguments[0] || {};
//对于发送错误信息的接口不收集,防止死循环
var regexp = new RegExp("https://xxxx/error","g");
if (regexp.test(options.url)) {
//这里要执行原来的方法
return originRequest.call(this, options)
}
//这里拦截请求成功或失败接口,拿到请求后的数据
["success", "fail"].forEach((methodName) => {
let defineMethod = options[methodName];
options[methodName] = function(){
try{ //在从新定义函数中执行原先的函数,不影响正常逻辑
defineMethod && defineMethod.apply(this, arguments);
//开始信息收集
let statusCode, result, msg;
//请求失败
if (methodName == 'fail') {
statusCode = 0;
result = 'fail';
msg = ( arguments[0] && arguments[0].errMsg ) || ""
}
//请求成功,
//收集规则为:
// 一、 statusCode非2xx,3xx
// 二、 statusCode是2xx,3xx,但接口返回result不为ok
if (methodName == 'success') {
let data = arguments[0] || {};
statusCode = data.statusCode || "";
if (data.statusCode && Number(data.statusCode) >= 200 && Number(data.statusCode) < 400 ) {
let resData = data.data ? (typeof data.data == 'object' ? data.data : JSON.parse(data.data)) : {};
//请求成功,不收集
if (resData.result == 'ok') {
return;
}
result = resData.result || "";
msg = resData.msg || "";
}else{
result = "";
msg = data.data || "";
}
}
//过滤掉header中的敏感信息
if (options.header) {
options.header.userid && (delete options.header.userid)
}
//过滤掉data中的敏感信息
if (options.data) {
options.data.userid && (delete options.data.userid)
}
var collectInfo = {
"url": options.url || '', //请求地址
"method": options.method || "GET", //请求方法
"request_header": JSON.stringify(options.header || {}), //请求头部信息
"request_data": JSON.stringify(options.data || {}), //请求参数
"resp_code": statusCode + '', //请求状态码
"resp_result": result, //请求返回结果
"resp_msg": msg, //请求返回描述信息
}
//提交参数与上一次不一样,或者参数相同,隔了1s
if (JSON.stringify(collectInfo) != lastParams.paramStr || (new Date().getTime() - lastParams.timestamp > 1000)) {
//上传错误信息
Post.post_error(_miniapp, 'http', collectInfo)
lastParams.paramStr = JSON.stringify(collectInfo);
lastParams.timestamp = new Date().getTime()
}
}catch(e){
//console.log(e);
}
};
})
return originRequest.call(this, options)
}
})
} catch (e) {
// Do something when catch error
}
}
复制代码
在不使用插件的小程序中,咱们能够在使用wx.request方法执行上面的代码,对wx.request进行拦截,而后其余无需加任何代码就能够收集http请求了。 上面说了,当咱们封装成到插件时,这个就无论用了,由于当使用插件时,小程序不容许咱们修改全局变量。因此执行上面代码时会报错。这时,咱们退而求其次,只能是在插件中本身封装个方法,这个方法其实就是wx.request发送请求,可是在插件中咱们就有能够拦截wx.request了。具体实现以下:
function my_request(){
//只要执行一次拦截代码便可
!_isInit && rewriteRequest();
return wx.request(options)
}
复制代码
接下来咱们看下后台数据
持续监控,会帮咱们找出不少隐藏的bug
洋洋洒洒写了这么多,或许有些地方说的不太清楚,慢慢锻炼吧。而后后面几点只是挑了重要的讲,我相信有太小程序开发经验的朋友应该没问题。而后有时间再补充和优化了。先到此,有缘看到的朋友,欢迎留言交流。