2023年11月28日发(作者:)

微信⼩程序开发总结与⼼得

0 前⾔

最近的⼯作重⼼⼀直在⼩程序,也开发了⼏个⼩程序,对⼩程序开发的流程及相关技术相对⽐较熟悉,在开发过程中也总结了⼀些⼼得经验、了解

⼀些⼩程序⽂档上没有的东西、踩了⼀些坑。所以想着写篇⽂章记录下来,并借此将⼩程序开发的相关知识进⾏梳理,⽅便以后参考,也作为⾃⼰

⼯作的阶段性总结。同时也希望可以通过⽂章,结识更多朋友,多交流,互相学习,共同进步。另⽂章若有不对之处,还望指出与不吝赐教。

1 微信⼩程序基本知识与概念

微信⼩程序开发,⼊门算是⾮常简单,只要看官⽂⽂档即可⼩程序简易教程。如何申请⼩程序账号,如何开发⾃⼰第⼀个⼩程序,如何发布,这⼀

系列hello world操作官⽅⽂档都有⼿把⼿教学。⼩程序开发的每个步骤,提供的能⼒⽂档⾥都有,个⼈觉得,做⼩程序开发,有事没事都看下⽂

档,因为⼩程序更新⽐较快速,同时⼀些细⼩的能⼒我们可能会漏掉,所以多看⽂档。

image

接下来简单介绍下各个⽂件:

全局配置⽂件app.json

对于⼀个⼩程序项⽬⽽⾔,最重要的⽂件是,它也是开发⼯具识别⼀个⽂件夹是否为⼩程序项⽬的标识。当使⽤开发者⼯具创建⼀个项

⽬是,如果选择的是空⽂件夹,它会创建⼀个新的项⽬。如果是⼀个有⽂件的⽂件夹,它会看该⽂件夹中是否有⽂件,如果有,则它会认

为是⼀个⼩程序项⽬,则会打开该项⽬,如果⽂件夹中没有⽂件,则提⽰⽆法创建项⽬。

image

必须放置于项⽬的根⽬录下,它是⼩程序项⽬的全局配置⽂件。在⼩程序代码包准备完成进⾏启动后(下⽂会详细介绍⼩程序从⽤户点

击打开⼩程序到⼩程序销毁的整个过程),会先读取⽂件,进⾏⼩程序的初试化,⽐如初始化整个⼩程序外框样式,获取⾸页页⾯地址

"pages": [

"pages/index/index",

"pages/log/log"

]

在中,pages选项是必须配置的。该配置项注册了⼩程序所有页⾯的地址,其中每⼀项都是页⾯的 路径+⽂件名 。配置的字符串其实就

是每个页⾯wxml路径,去掉.wxml后缀。因为框架会⾃动去寻找路径下.json、.js、.wxml、.wxss四个⽂件进⾏整合。也就意味着.json、.js、

.wxss这三个⽂件的⽂件名必须要和.wxml的⼀致,否则不⽣效。所以⼀个页⾯⾄少必须得有.wxml⽂件。

总结:

页⾯的.json、.js、.wxss⽂件必须与.wxml⽂件同名,否则不⽣效

每个页⾯都必须pages下注册,没有注册的页⾯,如果不访问,编译能通过,⼀旦试图访问该页⾯则会报错

可以通过在pages下添加⼀个选项快速新建⼀个页⾯,开发⼯具会⾃动⽣成对应的⽂件

window

"window":{

"enablePullDownRefresh": ture,

functionalPages

这个是结合插件使⽤的,因为微信⼩程序插件有很⼤限制,插件⾥提供的api很有限, 和 tPayment 在插件中不能使⽤,如

果需要获取⽤户信息和进⾏⽀付,就必须通过插件提供的功能也实现。当你的⼩程序下的插件启⽤了插件功能也时,必须设置该选项为true

⼩程序插件必须挂载在⼀个微信⼩程序中,⼀个⼩程序也只能开通⼀个插件。当你⼩程序开通的插件启⽤了插件功能也

时,必须设置该选项为true

image

⼩程序启动会有两种情况,⼀种是「冷启动」,⼀种是「热启动」。 假如⽤户已经打开过某⼩程序,然后在⼀定时间内

再次打开该⼩程序,此时⽆需重新启动,只需将后台态的⼩程序切换到前台,这个过程就是热启动;冷启动指的是⽤户⾸

次打开或⼩程序被微信主动销毁后再次打开的情况,此时⼩程序需要重新加载启动。

上⾯的流程图包含了所有内容,但毕竟⽂字有限,接下来详细说下⼏个点。

1. ⼩程序会先检测本地是否有代码包,然后先使⽤本地代码包进⾏⼩程序启动,再异步去检测远端版本。这就是⼩程序的离线能⼒,相对于H5,

这是优点,能加快⼩程序启动速度。

if (e('getUpdateManager')) {

//检测是否有版本更新

var updateManager = ateManager()

kForUpdate(function (res) {

// 请求完新版本信息的回调,有更新

if (ate) {

ading({

title: '检测到新版本',

})

}

})

teReady(function () {

ading();

dal({

title: '更新提⽰',

content: '新版本已经准备好,是否重启应⽤?',

success: function (res) {

if (m) {

//清楚本地缓存

image

可以模拟任意场景值、设置页⾯参数、模拟更新等。基本满⾜了所有的调试。不过还有⼀些效果,开发⼯具和真机可能会不同,所以还是需要在真

机上确认。

image

2 重点介绍⼏个组件

接下来说说使⽤频率⽐较多,功能强⼤,但⼜有⽐较多坑的⼏个组件

2.1 web-view

web-view的出现,让⼩程序和H5⽹页之前的跳转成为了可能。通过把H5页⾯放置到web-view中,可以让H5页⾯在⼩程序内运⾏。同时在H5页

⾯中也可以跳转回⼩程序页⾯。可以说是带来了很⼤的便利,但同时由于web-view的诸多限制,⽤起来也不是很舒服。

1. 需要打开的H5页⾯必须在后台业务页⾯中配置,这其中还有个服务校验。另外H5页⾯必须是https协议,否则⽆法打

2. web-view中⽆法在页⾯中调起分享,如果需要分享,⽐如跳回⼩程序原⽣页⾯

3. ⼩程序与web-view⾥H5通信问题。⼩程序向web-view传递,不敏感信息可以通过页⾯url传递。如果是敏感信息⽐如

⽤户token等,可以让服务端重定向,⽐如请求服务端⼀个地址,让他把敏感信息写在cookie中,再重定向到我们的

image

因为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 = temInfoSync();

if (res) {

var widHeight = Height;

//对于⼤多数⼿机,屏幕⾼度/屏幕宽度 = 1.78。此时导航栏占屏幕⾼度⽐为0.875

var raito = 0.875;

if (Height / Width > 1.95) {

//对于全屏⼿机,这个占⽐会更⾼些

raito = 0.885;

} else if (Height / Width > 1.885) {

raito = 0.88;

}

//做兼容处理,只有微信版本库⾼于6.7.2,有导航栏才去兼容,否则可以直接使⽤⾼度100%BarHeight是⼿机顶部状态栏⾼度

//如果微信版本号⼤于6.7.2,有导航栏

if (eVersion(n, "6.7.2") > 0) {

widHeight = (widHeight * raito) + (BarHeight || 0);

}

e({

//H5页⾯宽⾼拼接在url上,赋值给web-viewsrc即可加载出H5页⾯

webview_src: rams(h5_src, {

"height": widHeight,

"width": Width

})

})

}

}

wxml⽂件

scroll-with-animation = "true" style="height: 100%; white-space:nowrap">

2.3 canvas

画布标签,它是原⽣组件,所以它必须位于屏幕最上边,⽽且是不能隐藏的。所以如果想要使⽤canvas动态⽣成分享照⽚。那你要设置她的宽⾼

和屏幕⼀样。要不导出为照⽚时就会失真。因为这个原因,所以⽣成分享照⽚还是有服务端实现吧,照⽚失真太严重了。

3 formid收集

给⽤户发送消息对⼀个⼩程序是⾮常重要的,它可以召唤回⽤户,导量效果⾮常明显。我们可以通过模板消息想⼩程序⽤户发送消息,但前提是我

们得获取到openid和formid。⽤户登录我们即可即可获取到⽤户openid。⽽只要⽤户有点击⾏为,我们即可获取到formid获取formid。所以说

formid是很重要的。我们可以提前收集好formid,在需要的时候给⽤户推送消息。我们可以个每个button都包上form标签,只要有⽤户点击⾏

为都可以收集到formid.

我们实现⼀个formid收集系统,为了尽量减少冗余代码和减少对业务的影响,我们的设计是这样的

1. 在整个页⾯的最外层包裹form标签,不是每个button都包裹⼀个,这样只要是页⾯中的button有点击都能获取到formid。

formTpye=submit

2. formid保存在全局变量数组中,当⼩程序切换到后台是⼀次性发送。

3. 对于需要实时发送消息的,不添加值全局数组中,直接保存在页⾯变量中。

wxml⽂件

页⾯内容

页⾯内容

页⾯内容

⽂件

//每次⽤户有点击,都将formid添加到全局数组中

formSubmit(e) {

//需要实时发送的,不添加

if(g){

formid = ;

return;

}

();

}

image

前⾯状态⼩程序代码⼤⼩是650Kb左右,这是下载耗时(虽然跟⽤户⽹络有关,但这个是全部⽤户平均时间)是1.3s左右。但是经过优化,将代

码包降低⾄200kb左右时。下载耗时只有0.6s左右。所以说,代码包减少500kb,下载耗时能减少0.5s。这个数据还是⾮常明显和。所以说,在

不影响业务逻辑的情况下,我们⼩程序代码包应该尽可能地⼩。那么如何降低代码包⼤⼩呢?以下有⼏点可以参考

1. 因为我们上传代码到微信服务器时,它会将我们的代码进⾏压缩的,所以⽤户下载的代码包并不是我们开发时的那个⼤⼩。对此,开发时也没

必要删空⾏、删注释这些。在开发⼯具项⽬详情中可以看到上次上传⼤⼩,这个⼤⼩就是⽤户最终使⽤的⼤⼩。如果觉得微信压缩还不够好,

可以通过第三⽅⼯具对我们代码进⾏⼀次压缩再上传,然后对⽐效果,有没有更⼩。这个没有使⽤过。如果有什么好⼯具,欢迎推荐。

image

只不过错误信息是包括堆栈等⽐较详细的错误信息,然后当上传时我们并不需要这么信息,第⼀浪费宽带,第⼆看着累⼜⽆⽤。我们需要的信息

是:错误类型、错误信息描述、错误位置。

thirdScriptError

aa is not defined;at pages/index/index page test function

ReferenceError: aa is not defined

at (127.0.0.1:62641/appservice/pages/index/:17:3)

at e. (127.0.0.1:62641/appservice/__dev__/:16:31500)

enumerable: true,

writable: true,

value: function(){

let options = arguments[0] || {};

//对于发送错误信息的接⼝不收集,防⽌死循环

var regexp = new RegExp("xxxx/error","g");

if (()) {

//这⾥要执⾏原来的⽅法

return (this, options)

}

//这⾥拦截请求成功或失败接⼝,拿到请求后的数据

["success", "fail"].forEach((methodName) => {

let defineMethod = options[methodName];

options[methodName] = function(){

try{ //在重新定义函数中执⾏原先的函数,不影响正常逻辑

defineMethod && (this, arguments);

//开始信息收集

let statusCode, result, msg;

//请求失败

if (methodName == 'fail') {

statusCode = 0;

result = 'fail';

msg = ( arguments[0] && arguments[0].errMsg ) || ""

}

//请求成功,

//收集规则为:

};

})

return (this, options)

}

4 总结

洋洋洒洒写了这么多,或许有些地⽅说的不太清楚,慢慢锻炼吧。然后后⾯⼏点只是挑了重要的讲,我相信有过⼩程序开发经验的朋友应该没问