- 微盟小程序性能优化实践(上)
微盟小程序性能优化要分享的内容分为三部分,启动性能加载、首屏加载的体验建议和渲染性能优化。 今天主要讲启动性能加载的性能优化实践,先看启动加载过程的流程: [图片] · 公共库注入 · 资源准备(基础UI创建,代码包下载) · 业务代码注入和渲染 · 渲染首屏 · 异步请求 优化方案 1、控制代码包大小 · 开启开发者工具中的 “ 上传代码时自动压缩 ” · 及时清理无用代码和资源文件 · 减少代码包中的图片等资源文件的大小和数量 · 将图片等资源文件放到CND中 · 提取公共样式 · 代码压缩,图片格式,压缩,或者外联 · 公共组件提取,代码复用 2、 分包加载 分包加载过程流程 [图片] 在开发小程序分包项目时,会有一个或者多个分包,其中没有分包小程序必须包含一个主包,即放置启动页面或者tabBar页面,以及一些分包都需要用到的公共资源脚本。 在小程序启动时,默认会下载主包并且启动主包内页面,如果用户打开分包内的页面,客户端会把分包下载下来,下载完之后再进行展示。 · 分包加载流程 [图片] 使用分包加载的优点: · 能够增加小程序更大的代码体积,开发更多的功能 · 对于用户,可以更快地打开小程序,同时不影响启动速度 使用分包加载有哪些限制: · 整个小程序所有分包不能超过8M · 单个主包/分包不能超过2M 3、 运行机制优化 · 代码中减少立即执行的代码数量 · 避免高开销和长时间阻塞代码 · 业务代码都写入页面的生命周期中 · 做好缓存策略 4、 数据管理优化 · 首屏请求数量尽量不能超过5个,超过的可以做接口合并(node层,服务端都可以处理) · 对多次提交的数据可以做合并处理 首屏加载的体验建议和渲染性能优化这两部分的内容,将在下次分享给大家。微盟小程序性能优化实践(下)
2018-09-25 - 微信小程序性能优化实战指南:从加载速度到用户体验
一、引言在当今快节奏的移动互联网时代,小程序的加载速度和性能直接影响用户体验和留存率。根据腾讯官方数据,小程序首屏加载时间每增加1秒,用户流失率将提升10%。本文将结合实际案例,深入探讨微信小程序性能优化的关键策略和具体实现方法。 二、小程序加载速度优化1. 代码包体积优化问题分析:微信小程序代码包体积限制为2MB,代码包过大将导致下载时间延长。 优化方案: 合理使用分包加载:将非首屏或低频使用的功能模块进行分包处理移除无用代码和资源:定期清理未使用的组件、页面和资源文件图片资源优化:使用图片压缩工具对图片进行压缩处理[图片] 2. 图片资源优化问题分析:图片资源通常占小程序体积的较大比例,且不合理的图片加载会导致页面卡顿。 优化方案: 使用图片懒加载:仅当图片进入可视区域时才进行加载采用合适的图片格式:对于复杂图像使用JPEG,对于透明图像使用PNG,对于图标类使用SVG实现图片预加载:对于重要图片提前进行加载[图片] 3. 数据请求优化问题分析:过多、过大的数据请求会导致页面渲染延迟。 优化方案: 合并数据请求:将多个相关的数据请求合并为一个使用缓存机制:对于不经常变化的数据进行本地缓存优化请求频率:避免不必要的重复请求[图片] 三、运行时性能优化1. 渲染性能优化问题分析:频繁的setData操作和复杂的DOM计算会导致页面卡顿。 优化方案: 减少setData的数据量:只更新需要变化的数据控制setData的频率:避免在短时间内多次调用setData使用createSelectorQuery替代频繁的DOM操作[图片] 2. 内存管理优化问题分析:不合理的内存使用会导致小程序运行缓慢甚至崩溃。 优化方案: 及时清理定时器和事件监听器合理使用本地存储:避免存储过大的数据优化图片资源占用:在图片使用完毕后及时释放[图片] 3. 长列表优化问题分析:渲染大量数据的长列表会导致严重的性能问题。 优化方案: 实现虚拟列表:只渲染可视区域内的列表项分批加载数据:避免一次性加载大量数据使用下拉刷新和上拉加载更多的机制[图片] 四、优化效果评估1. 性能监测工具微信开发者工具中的性能面板:可查看小程序的加载性能和运行时性能自定义埋点:在关键流程添加性能埋点,收集实际用户的性能数据2. 优化前后对比通过实际数据对比可以看到,综合应用上述优化策略后,小程序的加载速度和运行性能都得到了显著提升: 首屏加载时间从原来的2.5秒缩短至1.2秒页面切换响应时间从平均500ms减少到200ms长时间使用后的内存占用降低了30%五、总结小程序的性能优化是一个系统性工程,需要从代码包体积、资源加载、数据请求、渲染性能等多个方面进行综合优化。通过本文介绍的优化策略和代码示例,开发者可以有效提升小程序的加载速度和运行性能,为用户提供更加流畅的使用体验。 在实际项目中,建议根据小程序的具体情况有针对性地选择优化方案,并通过性能监测工具持续跟踪优化效果,不断迭代和完善优化策略。
05-13 - 使用独立分包和分包预下载(上)
[视频] 你好,我是李艺。 上节课我们学习了按需注入和初始渲染缓存,明确了静态导航页适合使用初始渲染缓存,动态详情页适合使用骨架屏的策略。这节课我们学习分包、独立分包以及分包预下载。 首先我们看一下问题,在冷启动流程中间使用按需注入改良的只是代码注入阶段的性能,如果这个代码包本身它就比较大,那么在第一阶段,也就是资源准备阶段,就会浪费大量的时间,还有如果是代码包过大,它主包超过2MB,在微信开发者工具里面根本也没有办法上传以申请这个版本的审核,为了让这个代码包瘦身,微信开发者工具提供了静态代码依赖分析这个工具,可以帮助开发者找到无依赖文件。 但是有一点我们需要注意,有一些文件它表面上看起来是用不到的,但其实是不能删除的,因为有时候它是在运行时动态加载并使用的,如果这个代码包删除了无依赖的文件以后依然超过了2MB的限制,这时候应该怎么办?小程序又提供了分包以及独立分包的机制,只要单个代码包不超过2MB,总包大小不超过20MB即可。有些开发者可能觉得2MB限制太小了,决定阈值的从来其实都不是规定,而是网络环境和用户群体,国内有很多网民还在使用低端机,包括WiFi以及4G网络环境其实还没有100%的普及,或许等以后5G技术普及以后,限制会进一步的放开,那个时候主包大小或许会进一步的放大,在目前这个阶段,在当下网络环境里面如果要想提升小程序的启动性能以及运行性能,只能在深谙小程序的运行机制以及启动流程的前提之下,在已有的技术框架之下靠精耕细作的精神一个字节 一个字节地去优化。 接下来我们看项目实践。 目前我们的项目已经超过了2MB,必须通过分包分割总代码包的大小。 首先我们看实践一:用户主页分包、创建tab-bar组件。 将用户主页放在分包内,只需要给页面所在的目录添加分包配置就可以了,在app.json全局配置文件里面,我们可以在subpackages这个节点之下添加一个分包设置,root设置为当前页面所在的目录的一个名称,然后再加上pages设置就可以完成用户主页的一个分包设置了。 在小程序里面,如果是使用配置的方式开启tabBar导航,或者是使用这种官方自定义的方式,也就是我们通过在配置文件里面设置tabBar.custom等于true这样的方式实现tabBar导航组件,这个时候tabBar它页面地址只能放在主包里面,为了破除这个限制,我们可以使用自定义的方式实现tabBar的导航。 首先我们需要在app.json配置文件里面将tabBar的配置删掉,我们现在不需要这个配置了,然后我们在components目录下面创建一个tabBar的组件,用它提供全局的导航功能,在组件的JS代码里面会创建一个select方法,它设置哪个链接,当前是选中的状态,这个方法是给外部的代码进行提供的,这个组件的wxml代码很简单,主要是渲染一个list列表,而且这个list的数据还是从原来app.json文件里面复用过来的,wxss样式仅包含自定义组件本身它所需要的样式,这个里边有一个特殊的类样式,就是bar__active。这个是选中的样式,当这个链接与当前这个页面地址一致的时候这个文本它会呈现红色,这个图标也是红色图标,文本的选中颜色还有文本的默认颜色也就是它默认呈现的颜色,与我们原来在app.json配置文件里面的设置是一致的,完全以自定义组件这种方式实现的tabBar导航有哪些优点?我们一起看一下。 首先第一点,页面不再受分包的限制。我们可以将这个页面放到任何一个分包里面去;第二点就是tab-bar组件里边用到的图标,也不再被限制只能放在本地;第三点就是这个代码里面所有的tabBar页面的跳转也不用再单独使用wx.switchTab这样的接口,可以统一使用wx.navigateTo或者是wx.redirectTo这两个接口任何一个都可以,甚至tab-bar组件本身,如果我们愿意的话还可以将它进一步的优化,不放在主包里边,放在分包里面也是可以的。 现在我们开始实践一的代码演示。 在拿到这个源码以后,我们需要在小程序里面进行一个代码的引入,引入方式也很简单,只需要找到对应的目录然后选择,选择以后这个地方AppID要选择我们自己的账号的AppID,这个名称也可以修改,然后单击确定就可以了。我们要实现分包,实现用户主页的一个分包,首先我们看一下app.json这个文件,这个文件里面,目前我们这个地方其实已经有了一个分包设置了,在subpackages下面只需要在这个底下再添加一个新的配置就可以了。这个里面第一个字段要写的是root,它代表的是我们分包的一个地址,这个地方我们写user,因为我们这个项目底下确实有一个user的目录,也就是这个,根目录指定以后,接下来我们要指定pages,也就是这个页面了,这个页面它是我们在分包下面的一个相对地址,我们可以在这个地方复制一个相对路径,然后粘到这个地方,前面这些是不需要的,它只需要从pages下面,也就是从我们目录下面,开始计算路径,这样的话我们分包的一个设置就算是已经完成了。 再往下我们再创建我们的自定义导航按钮,自定义导航的组件在我们的components目录下面,然后去创建这个组件,现在这个目录还没有,可以创建一下目录,然后这个目录下面再创建一个tab_bar这样的子目录,在这个目录下面放tab-bar自定义组件它的一个源码,可以采用一种快速的新建的方式,比如这个地方我们选择新建Component选择这个菜单,然后写入一个index,完成以后,下面所有的四个文件已经全部默认帮我们创建了,下面开始实现这个代码,这个代码我们之前这已经有实现好的,为了快速我们直接复用我们已经实现的代码,这是页面的标签代码,这个标签代码里面我们可以看一下,主要是一个列表渲染,这个地方用了一个wx:for这样一个列表渲染,然后循环渲染这个list里边还有关于image这个地方有一个判断,当前的index是否等于selected就是我们当前选择的索引,如果等于的话,然后去渲染这样的一个图标地址,如果否的话就是选择另外一个图标地址,这是它的样式。 这个地方是我们这个页面的就是文本 一个标题或者说我们页面的一个名称,这个页面的一个跳转是靠我们绑定的一个事件,在这个上面可以看一下,在这个地方有一个tap 一个绑定,nav的方法上面,我们再看一下JS代码,这是我们JS代码,这个JS代码里面nav,这是我们刚才提到的用于页面跳转的一个方法,上面这有一个select它的参数是index就是索引,我们当前选择哪一个,这个方法是对外提供的,在这个页面里面使用这个组件的时候,稍后我们会调用这个方法。 再往上就是data对象了,第一个是一个selected,就是选择的索引,我们当前选择这列表里面哪一项作为选中的页面,它的默认是0,下面这个list这些数据是我们原来的app.json里面的数据,它的一个修改,我们可以看一下我们原来的数据这个地方 这有一个list,我们可以将这个list给它拷贝一下,除了这个list还有两个color,这里有一个color 这有一个color,我们先将这个list给它拷贝一下,然后到tab_bar这个里面,可以放在这个地方对比一下,这两个数据是很像的,它的差别其实只是我们pagePath前面多了一个斜杠,包括iconPath还有selectedIconPath前面多了两个斜杠,其他的其实都是一样的。 当然了我们上面的这种格式是微信它定义的,在app.json里面,如果是要定义tabBar导航的话必须要用这种格式,但下面这种格式是我们自定义的,我们选择这样一种方式定义便于我们和默认的官方配置、保持一致的数据结构,最后我们再看一下样式。这个代码里面只有一项就是component等于true,如果它是个组件的话,在这个json里边它这一项是等于true的样式代码,这是它的一个样式代码,在样式代码里面可以看到这个里面有一个bar__active代表的是选中状态,选中状态下它文本色,这个地方其实是文本,我们可以看到在这个里边这是它的样式,选中以后文本变成这个颜色,d81e06这样的一个样式与我们前面在这个地方看到的样式它俩是一样的,包括我们前面的5151默认的文本颜色跟我们组件里面的样式也是一样的。我们可以看一下,也就是这个颜色,这是它默认的一个颜色,是一样的。这是组件已经准备好了,这个它默认生成的,其实下面那个我们不需要,只需要这一个就可以了,组件已经准备好了。 接下来我们需要在配置文件里面做一个组件的引入,在这个里面也需要写一个usingComponents,然后是tab-bar,一般的话自定义组件的命名方式就使用这样一种单词中间用连字符,因为官方它组件,然后分割单词也是这样一种形式,所以我们就沿用官方的形式就可以了,组件的地址在哪里,这个地方可以复制一下相对地址,然后粘到这个地方再稍做修改这样就可以了,稍做修改,当然后面JS不需要 把这个给去掉,接下来我们就需要在我们的三个页面:用户主页、商品详情页和主页面里面分别添加tar-bar组件的一个使用。 首先我们在user这个里面找到这个标签页wxml这个页面,在它的最下方添加一个tab-bar,再给它一个id,这样一个代码,然后我们还需要在JS里面,在这个页面的onReady的时候onReady,这个地方没有onReady就在这个地方再加一个onReady,在这个地方需要调用这个页面的selectComponent这个地方的参数,我们写#tabBar 井号代表的是id,tabBar是我们刚才定义的id,选择以后再调用它的select方法,要传一个参数,因为我们用户主页居于导航栏的里面的属于它的索引在2这个位置,所以我们这地方要选2。这是用户主页,然后将这个代码复制一下,在另外的两个页面里面,一个是商品详情页,在这个页面最下方也拷贝一份,还有是我们的index主页的最下方也放置一份,这是wxml代码,接着是拷贝我们的选择代码,在主页里面找到onReady,在这个地方可以放在最后面 放在这个位置,这个是主页,数字要设置为1,还有一个是商品详情页,商品详情页在onReady里边添加代码,这个要设置为0,这就是我们的代码,现在已经改造完成了。 单击编译我们看一下运行效果。这个地方有一个问题,就是我们的地址它不应该在subPackages分包内出现这样的一个提示,这个提示是什么意思,看一下我们这个项目的配置文件,现在我们给用户主页实现分包,将这个地址放在了这个地方,当然这个地方多了一个.js,放在这个地方以后,在我们整个文件默认的pages下面,这个地址其实我们就应该给它删掉,它不需要了,一个页面不能同时出现在两个包里,然后这样去处理再编译一下 看看效果。 这个地方也有一个问题,模拟器无法获取这个文件,已经被忽略上传,它这个忽略上传我们暂时不要去理它,只是它自己的一个提示,现在要测试导航组件的一个表现是否正常,选择商品页,商品页现在高亮了对吧,然后选择主页,然后主页高亮了对吧,然后选择我的页面,我的页面也高亮了对吧。这个导航已经实现了它预想的一个功能,现在我们拿我们的商品详情页,就是detail这个页面它作为启动页再测试一下,也没有问题对吧,也显示了这个代码它的作用是良好的。 在这个地方有一点我们需要提示一下,我们这个代码里面是有选择组件,然后再调用其中的方法的代码也就是这个对吧,在主页里面这个地方选择组件然后再调用它的方法,选择这个组件它其实未必是可以选到的,所以如果这个地方我们要避免出错的话我们可以加一个问号,加个问号以后 就是ES6里面的可选链语法,如果是它不是null,然后找到这个组件,调用它的一个方法,这样的一个语法,这是主页,然后在这个商品详情页里面也是一样的一个处理,这个地方加一个问号,还有一个是在用户主页这个地方也加一个,我们再测试一下,没有问题。正常情况下这个页面已经走到了onReady这个地方,按理说它不会出现选择不到的这种情况,但是有一种情况我们稍后可能会遇到,如果是我们当前这个页面,它本身它跟我们的用到的组件,我们现在这个组件tab-bar这个组件是放在我们主包里面,因为它是在app.json里面配置的,如果是我们这个页面是在一个独立分包里面 它是独立的,然后它显示的时候其实主包没有加载,主包里边的组件你也使用不了,这种情况下有可能,这个地方我们要去选择组件的时候,它可能拿到的是一个空值或者是一个undefined,你在一个undefined调用它的方法,显然是不合适的话可能会报错,所以这个地方所有的组件其实都是一样,你如果想万无一失的话,给它加一个问号,这个问题就可以轻松化解了。 这个代码演示就到这里了。
2022-07-14 - 小程序已支持长按识别二维码
查阅了很多文章,大多还停留在页面嵌入webview识别二维码的时代。 [图片] 下面我发表一下小程序支持长按识别二维码的方法 只需要在image标签里添加 如下属性 小程序版本: show-menu-by-longpress="{{true}}" uniapp版本: :show-menu-by-longpress="true" 例如: 小程序版本: <image class="pic" show-menu-by-longpress="{{true}}" :src="src" mode="widthFix" /> uniapp版本: <image :src="src" mode="widthFix" :show-menu-by-longpress="true"></image> 即可长按识别,快去试试吧!
2023-02-03 - 小程序如何监听手机是否开启录屏?防止用户录屏
使用wx.getScreenRecordingState可以监听ios系统。如何监听android系统、鸿蒙系统、window、os系统?
06-20 - 小程序跳转公众号的三种方法
一、方法 方法1: 直接放个公众号二维码, 在小程序里长按识别, 就能跳了 (最简单) 方法2: 公众号组件[代码]<official-account></official-account> 跳转 (场景有要求)[代码] 方法3: webview内嵌的公众号链接, 可以直接跳 (需要配置下) 二、讲解 1) 、方法1就不介绍了; 2)、 方法2: <official-account></official-account> 公众号引导关注; 官方文档 https://developers.weixin.qq.com/miniprogram/dev/component/official-account.html [图片] [图片] 3)、 方法3: [图片][图片] 满足一些条件, 就能直接webview嵌入公众号页面, 点击就能快速跳转到公众号 <web-view src="https://mp.weixin.qq.com/s/cCcDcAkqzoyZVPChfMfqUw"></web-view> 直接能放 公众号 链接或者文章链接 1,登入微信公众号的管理后台 微信公众平台。 2,选择要跳转的公众号登录进去,点击小程序管理。 [图片] 3,直接点击关联小程序即可,如果关联过其他小程序点击添加即可,该操作只能由公众号管理员完成,如果你不是管理员,让管理员扫一下该操作的二维码即可关联小程序。 [图片] 4,退出微信公众号的登录,重新扫码,登进小程序的后台,点击设置。 [图片] 5,选择关注公众号,打开引导关注公众号,可通过公众号的名字关联 [图片] 小程序的公众号是认证的企业号,那么,就用不上上面那么多的步骤了,直接新开一个页面,在页面中写<web-view>就可以了 更多参考: https://www.cnblogs.com/520BigBear/p/16931629.html
2023-04-17 - 小程序中跳转页面,提示页面不存在?
小程序进入首页正常,在首页点击功能按钮进去其他页面,跳转后提示页面不存在,偶现问题,目前有一位用户进行反馈,请社区运营帮忙排查一下,给个结论[图片]
2023-02-23 - 开发工具自动修改project.config.json文件问题
[图片] 微信开发工具内置 vs code 编辑器,默认配置 \r\n,也就是 crlf 换行符,如果与项目或者git全局设置的换行符不同,那么每次打开开发工具,就会自动修改这个文件,从而导致 git checkout,git add 等一系列操作问题。 以上问题,可以找到开发工具的 vs code 配置,与本地项目或 git 设置保持一致即可。 [图片] 例如:项目配置的 end_of_line 为 lf,此时将开发工具换行符,改为 \n 即可。 另外也可检查 git config,合理配置。 project.config.json 与 project.private.config.json 文件: 二者都是项目启动的配置文件,但后者是本地开发工具的配置,默认被 gitignore 处理,使得提交代码时,不易与其他同事发生代码冲突。也就是说,如果要开启某项调试,我们可以在后者中加入自己的个性化配置。 mock.config.json 文件: 该文件为开启mock本地调试后导出生成,可以联调未发布的接口,以及交互流程。
2023-09-22 - 按微信号发布,灰度白名单用户没有命中新版本
1、按微信号发布,同时选择了「项目成员与体验成员」和「对话框输入-灰度白名单的微信号」 2、「项目成员与体验成员」进入新版本 3、「对话框输入-灰度白名单的微信号」没有进入新版本 4、产品Appid wx9796f762a252711a 请问这两个选择,互斥 or 同时 另外建议,输入名单的地方,也可以输入一个微信号,确认一个,one by one [图片]
2024-07-10 - 教你怎么监听小程序的返回键
更新:2020年7月28日08:51:11 基础库2.12.0起,可以调用wx.enableAlertBeforeUnload监听原生右上角返回、物理返回以及wx.navigateBack时弹框提示 AIP详情请看: https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.enableAlertBeforeUnload.html //======================================== 怎么监听小程序的返回键? 应该有很多人想要监听用户的这个动作吧,但是很遗憾,小程序不会给你这个API的,那是不是就没辙了? 幸好我们还可以自定义导航栏,这样一来我们就可以监听用户的这一动作了。 什么?这你已经知道啦? 那好咱们就不说自定义导航栏的返回监听了,说一下物理返回和左滑?右滑?(不管了,反正是滑)返回上一页怎么监听。 监听物理返回 首先说一下这个监听方法的缺点,虽说是监听,但是还是无法真正意义上的监听并拦截来阻止页面跳转,页面还是会返回上一页,而后重新载入刚刚的页面,如果这不是你想要的,那可以不用往下看了 其次说一下用到什么东西: wx.onAppRoute、wx.showModal 最后是一些主要代码: 重写wx.showModal,主要是加个confirmStay参数和使wx.showModal Promise化 [代码]const { showModal } = wx; Object.defineProperty(wx, 'showModal', { configurable: false, // 是否可以配置 enumerable: false, // 是否可迭代 writable: false, // 是否可重写 value(...param) { return new Promise(function (rs, rj) { let { success, fail, complete, confirmStay } = param[0] param[0].success = (res) => { res.navBack = (res.confirm && !confirmStay) || (res.cancel && confirmStay) wx.setStorageSync('showBackModal', !res.navBack) success && success(res) rs(res) } param[0].fail = (res) => { fail && fail(res) rj(res) } param[0].complete = (res) => { complete && complete(res) (res.confirm || res.cancel) ? rs(res) : rj(res) } return showModal.apply(this, param); // 原样移交函数参数和this }.bind(this)) } }); [代码] 使用wx.onAppRoute实现返回原来的页面 [代码]wx.onAppRoute(function (res) { var a = getApp(), ps = getCurrentPages(), t = ps[ps.length - 1], b = a && a.globalData && a.globalData.pageBeforeBacks || {}, c = a && a.globalData && a.globalData.lastPage || {} if (res.openType == 'navigateBack') { var showBackModal = wx.getStorageSync('showBackModal') if (c.route && showBackModal && typeof b[c.route] == 'function') { wx.navigateTo({ url: '/' + c.route + '?useCache=1', }) b[c.route]().then(res => { if (res.navBack){ a.globalData.pageBeforeBacks = {} wx.navigateBack({ delta: 1 }) } }) } } else if (res.openType == 'navigateTo' || res.openType == 'redirectTo') { if (!a.hasOwnProperty('globalData')) a.globalData = {} if (!a.globalData.hasOwnProperty('lastPage')) a.globalData.lastPage = {} if (!a.globalData.hasOwnProperty('pageBeforeBacks')) a.globalData.pageBeforeBacks = {} if (ps.length >= 2 && t.onBeforeBack && typeof t.onBeforeBack == 'function') { let { onUnload } = t wx.setStorageSync('showBackModal', !0) t.onUnload = function () { a.globalData.lastPage = { route: t.route, data: t.data } onUnload() } } t.onBeforeBack && typeof t.onBeforeBack == 'function' && (a.globalData.pageBeforeBacks[t.route] = t.onBeforeBack) } }) [代码] 改造Page [代码]const myPage = Page Page = function(e){ let { onLoad, onShow, onUnload } = e e.onLoad = (() => { return function (res) { this.app = getApp() this.app.globalData = this.app.globalData || {} let reinit = () => { if (this.app.globalData.lastPage && this.app.globalData.lastPage.route == this.route) { this.app.globalData.lastPage.data && this.setData(this.app.globalData.lastPage.data) Object.assign(this, this.app.globalData.lastPage.syncProps || {}) } } this.useCache = res.useCache res.useCache ? reinit() : (onLoad && onLoad.call(this, res)) } })() e.onShow = (() => { return function (res) { !this.useCache && onShow && onShow.call(this, res) } })() e.onUnload = (() => { return function (res) { this.app.globalData = Object.assign(this.app.globalData || {}, { lastPage: this }) onUnload && onUnload.call(this, res) } })() return myPage.call(this, e) } [代码] 在需要监听的页面加个onBeforeBack方法,方法返回Promise化的wx.showModal [代码]onBeforeBack: function () { return wx.showModal({ title: '提示', content: '信息尚未保存,确定要返回吗?', confirmStay: !1 //结合content意思,点击确定按钮,是否留在原来页面,confirmStay默认false }) } [代码] 运行测试,Oj8K 是不是很简单,马上去试试水吧,效果图就不放了,静态图也看不出效果,动态图懒得弄,想看效果的自己运行代码片段吧 代码片段 https://developers.weixin.qq.com/s/hc2tyrmw79hg
2020-07-28 - 小程序密码输入安全键盘参数疑问?
这几个参数都是什么意思,如何填写呢? 官方文档:https://developers.weixin.qq.com/miniprogram/dev/component/input.html [图片]
2021-08-01 - 小程序全局弹窗如何实现啊?
最近公司有个需求,后台发公告,发布成功小程序需要弹一个窗展示公告内容,这个弹窗要全局且实时在任何一个页面都能自动弹出,请问这种应该如何实现,求大佬们给个思路
2024-01-23 - 小程序全局工具栏:提升用户体验的新利器
[图片] 在过去的小程序开发过程中,全局工具栏一直是开发者们急需解决的问题。然而,小程序并未直接支持此功能,开发者们只能采用自定义组件方式来实现。这种方法需要在每个页面的 wxml 中引入组件,导致大量重复代码,同时状态同步过程复杂且不够顺滑,给开发者带来了很大的困扰。 为了解决这个头疼的问题,Skyline 已经支持了小程序全局工具栏功能。这个全新的功能将大大简化开发流程,提升用户体验和操作便利性。全局工具栏可以实现跨页面渲染和状态同步,其渲染层级位于页面之上,使得用户在不同页面间切换时,工具栏的状态能得到保持,大大增强了操作的便利性。 接下来的文章中,我们将详细介绍小程序全局工具栏的使用流程,希望能帮助开发者们更好地理解和应用这一强大的功能~ 使用步骤通过以下三个步骤,你将能够轻松实现全局工具栏的功能: 1、配置信息:首先,在 app.json 文件中添加 appBar 选项,如下所示: { "appBar": {} } 2、添加 appBar 代码文件:在代码根目录下添加入口文件,包括以下四个文件: app-bar/index.js app-bar/index.json app-bar/index.wxml app-bar/index.wxss 3、编写 appBar 代码:使用自定义组件的方式编写 appBar 代码。在 app-bar/index.js 文件中,创建一个自定义组件实例,并在 app-bar/index.wxml 文件中编写组件的结构。同时,可以在 app-bar/index.wxss 文件中添加样式。最后,在需要获取 appBar 组件实例的页面中,使用 getAppBar 接口获取实例,进行操作。例如: Page({ getInstance() { if (typeof this.getAppBar === 'function') { const appBarComp = this.getAppBar(); appBarComp.setData({}); } } }); 通过以上三个步骤,你已经成功实现小程序全局工具栏,从而简化开发流程并提升用户体验和操作便利性~ 注意事项和限制在使用小程序全局工具栏时,我们需要关注以下几点注意事项和限制,以确保功能的正常运行: app-bar 组件仅支持 Skyline 渲染,Webview 渲染不支持,需确保项目采用 Skyline 渲染引擎以实现全局工具栏功能。在 Webview 渲染和 Skyline 渲染之间混跳时,全局工具栏的状态同步会受到影响,需要注意在跳转页面时处理状态变化。由于全局工具栏的渲染层级位于页面之上,需要避免与其他页面元素发生层叠覆盖,确保留出足够的空间容纳全局工具栏,避免影响用户体验。全局工具栏功能需要 v3.3.1 及以上的小程序基础库版本支持。遵循以上注意事项和限制,开发者将能够更好地利用小程序全局工具栏功能,提升用户体验和操作便利性。 案例展示我们通过实际案例来介绍小程序全局工具栏的应用场景~ 以微信学堂为例,我们可以使用全局工具栏来实现课程播放栏的功能。在课程播放的过程中,我们可以浏览其他课程、查看课程介绍等等。在这种情况下,实现一个全局的课程播放栏可以很好地提升用户体验。借助小程序全局工具栏,我们可以轻松实现这一功能~ [图片] 接下来,让我们来看看具体的代码实现~ 使用十分简单,我们参照使用步骤建立 app-bar 组件,然后我们只需要在 app-bar 组件中实现我们的业务代码即可。 我们的课程播放器还结合了手势和 worklet 动画,实现了最小化和最大化全局工具栏的效果,用户可以根据自己的需要来切换全局工具栏的大小,提高用户使用体验,实现更加丰富和高效的用户界面~ 在 app-bar/index.wxml 中,实现的代码与我们平时写自定义组件无异,可以根据业务诉求实现自定义的组件,我们这里展示了课程播放器的实现。 <!-- app-bar/index.wxml --> <vertical-drag-gesture-handler worklet:ongesture="handleVerticalDrag"> <view class="expand-container"> <!-- 最大化展示:nav-bar --> <view class="nav-bar column"></view> <!-- 跟着手势变化,改变组件的展示效果 --> <view class="cover-area" style="height: {{maxCoverSize}}px;"> <view class="row " bind:tap="expand"> <!-- 跟着手势改变宽高 --> <image class="cover" mode="aspectFill" src="{{musicCover}}" /> <!-- 最小化展示:标题、按钮 --> <view class="title-wrap row-between"> <view class="title column"> <text overflow="ellipsis" max-lines="1">Skyline 渲染框架入门与实践</text> <text class="name" overflow="ellipsis" max-lines="1">小程序技术专员 - binnie</text> </view> <view class="row"> <image class="icon" style="margin-right: 24px;" src="/assets/play.png" /> <image class="icon" src="/assets/next.png" /> </view> </view> </view> </view> <!-- 最大化展示:详情内容 --> <view class="music-title">...</view> <view class="footer">...</view> </view> </vertical-drag-gesture-handler> 因为我们在 wxml 中使用了手势系统,所以我们需要给手势加上手势事件,这样我们就实现了一个顺滑的课程播放器啦~ 如果你还没有学习过 worklet 动画和手势系统,建议可以学习一下 worklet 动画 和 手势系统,了解之后你将更好地理解我们在课程播放器中使用的手势和 worklet 动画的实现方式,同时,worklet 动画和手势系统也可以帮助你实现更加复杂和丰富的用户界面。 Component({ lifetimes: { attached() { const progress = shared(0) // 通过 worklet 改变各个组件的状态 this.applyAnimatedStyle('.cover', () => { 'worklet' ... }) this.applyAnimatedStyle('.expand-container', () => { 'worklet' ... }) this.applyAnimatedStyle('.title-wrap', () => { 'worklet' return { opacity: 1 - progress.value } }) this.applyAnimatedStyle('.nav-bar', () => { 'worklet' ... }) this.progress = progress } }, methods: { // vertical-drag-gesture-handler 绑定的手势事件 handleVerticalDrag(evt) { 'worklet' if (evt.state === GestureState.ACTIVE) { const delta = evt.deltaY / screenHeight this.handleDragUpdate(delta) } else if (evt.state === GestureState.END) { const velocity = evt.velocityY / screenHeight this.handleDragEnd(velocity) } else if (evt.state === GestureState.CANCELLED) { this.handleDragEnd(0.0) } }, // 手势变化时 handleDragUpdate(delta) { 'worklet' const curValue = this.progress.value const newVal = curValue - delta this.progress.value = clamp(newVal, 0.0, 1.0) }, // 手势结束时 handleDragEnd(velocity) { 'worklet' ... if (animateForward) { this.progress.value = timing( 1.0, { duration: 200, easing: animationCurve, }) } ... } } }) 以上是我们实现课程播放器的核心代码,如果您想要进一步了解和实践,可在 PC 端点击 代码片段 进行调试。 总结小程序全局工具栏为用户提供了更加便捷的操作方式和更丰富的功能,让小程序的使用体验得到了显著提升。通过全局工具栏,用户可以在不同页面间快速切换,轻松访问常用功能,同时还可以自定义工具栏,满足个性化需求。此外,全局工具栏还可以帮助开发者提高用户粘性,提升小程序的活跃度。 小程序全局工具栏适用于多种场景,如电商平台、在线教育、新闻资讯、工具类等。例如,电商平台可以将购物车、订单等入口放置在全局工具栏上,方便用户随时查看和管理;在线教育平台可以将课程列表、学习记录等功能放置在全局工具栏上,方便用户快速找到所需内容。 小程序全局工具栏是一个非常实用的功能,可以帮助用户更好地使用小程序,同时也为开发者提供了提升用户体验和增加用户粘性的机会。我们邀请大家尝试将小程序全局工具栏这个能力应用到自己的小程序上,为用户带来更好的使用体验~
2024-02-21 - 请问: 小程序关闭之后, 在微信内部的缓存时间是多长时间?
当小程序关闭之后, 在微信内部的缓存时间是多长时间? 多长时间再次进入小程序之后, 小程序会初始化
2019-12-04 - 如何在用户关注公众号时获取到用户的openid?
如何在用户关注公众号时获取到用户的openid?
2021-03-11 - 同一个微信,同一个小程序,更换不同手机号登录数据为什么一直是微信绑定的这个手机号的?
同一个微信,同一个小程序,使用微信快速登录切换不同手机号进行登录时,应该通过什么方法去获取不同手机号的数据? 使用 @getphonenumber 获取到的 openid 和 unionid 都是同一个。
2023-09-23 - 小程序app.onLaunch与page.onLoad异步问题的最佳实践
场景: 在小程序中大家应该都有这样的场景,在onLaunch里用wx.login静默登录拿到code,再用code去发送请求获取token、用户信息等,整个过程都是异步的,然后我们在业务页面里onLoad去用的时候异步请求还没回来,导致没拿到想要的数据,以往要么监听是否拿到,要么自己封装一套回调,总之都挺麻烦,每个页面都要写一堆无关当前页面的逻辑。 直接上终极解决方案,公司内部已接入两年很稳定: 1.可完美解决异步问题 2.不污染原生生命周期,与onLoad等钩子共存 3.使用方便 4.可灵活定制异步钩子 5.采用监听模式实现,接入无需修改以前相关逻辑 6.支持各种小程序和vue架构 。。。 //为了简洁明了的展示使用场景,以下有部分是伪代码,请勿直接粘贴使用,具体使用代码看Github文档 //app.js //globalData提出来声明 let globalData = { // 是否已拿到token token: '', // 用户信息 userInfo: { userId: '', head: '' } } //注册自定义钩子 import CustomHook from 'spa-custom-hooks'; CustomHook.install({ 'Login':{ name:'Login', watchKey: 'token', onUpdate(token){ //有token则触发此钩子 return !!token; } }, 'User':{ name:'User', watchKey: 'userInfo', onUpdate(user){ //获取到userinfo里的userId则触发此钩子 return !!user.userId; } } }, globalData) // 正常走初始化逻辑 App({ globalData, onLaunch() { //发起异步登录拿token login((token)=>{ this.globalData.token = token //使用token拿用户信息 getUser((user)=>{ this.globalData.user = user }) }) } }) //关键点来了 //Page.js,业务页面使用 Page({ onLoadLogin() { //拿到token啦,可以使用token发起请求了 const token = getApp().globalData.token }, onLoadUser() { //拿到用户信息啦 const userInfo = getApp().globalData.userInfo }, onReadyUser() { //页面初次渲染完毕 && 拿到用户信息,可以把头像渲染在canvas上面啦 const userInfo = getApp().globalData.userInfo // 获取canvas上下文 const ctx = getCanvasContext2d() ctx.drawImage(userInfo.head,0,0,100,100) }, onShowUser() { //页面每次显示 && 拿到用户信息,我要在页面每次显示的时候根据userInfo走不同的逻辑 const userInfo = getApp().globalData.userInfo switch(userInfo.sex){ case 0: // 走女生逻辑 break case 1: // 走男生逻辑 break } } }) 具体文档和Demo见↓ Github:https://github.com/1977474741/spa-custom-hooks 祝大家用的愉快,记得star哦
2023-04-23 - 小程序中如何使用Crypto进行加解密
该插件完全前端化,无任何服务器端调用,请放心使用。如果不放心可用fiddler截取插件包查看相关源码。 登录微信公众平台 https://mp.weixin.qq.com,输入小程序账号密码。 [图片] 点击设置,打开第三方服务,点击添加插件。 [图片] 搜索 Crypto 或者 wxf25d506ff81e19fb [图片] 搜索结果出来后选中 Crypto ,点击添加。 [图片] 配置小程序app.json 加入 "plugins":{ "crypto":{ "version":"0.0.003", "provider":"wxf25d506ff81e19fb" } } 注: version填0.0.002也可使用,0.0.002没有 PBKDF2 加密方式及 RSA 非对称加解密方式 在小程序代码中声明引用 const crypto = requirePlugin("crypto"); 使用MD5加密 new crypto["MD5"]("布包云").toString(); 使用AES 进行加解密 const mi = new crypto.AES().encrypt('布包云', "BubaoCloud", { iv: 8, mode: crypto.Mode.CBC, padding: crypto.Padding.Pkcs7 }); console.log('encrypt:', mi.toString()); const v = new crypto.AES().decrypt(mi.toString(), "BubaoCloud", { iv: 8, mode: crypto.Mode.CBC, padding: crypto.Padding.Pkcs7 }); console.log('decrypt:', v.toString(crypto.Utf8));
2018-11-07 - 订阅通知关于长期订阅可以多一些模板吗?一次性真的不够用啊~
我们是做广州地区的限行服务,用户开车进入限行区域,我们会发推送提醒(我们有一个定位设备,用户触发后的通知消息);并且每晚都会推送通知来告知用户第二天是否限行,这个变动大大影响了公众号服务和用户体验。用户每天都需要出行,他们也没有办法时刻记得去点击一次性订阅。贴上两个公众号appid:wx34a84f4d26f72830;appid:wxa10005510631fe7a。 【1】订阅通知关于长期订阅,可以多一些模板,根据不同行业不同服务,我们可以提交模板审核,由官方挑选出符合长期订阅的模板。 【2】每个开发者提交模板审核更加严格之外,对骚扰性质的推送进行严厉惩罚。
2021-02-20 - 长期订阅新增模板在哪申请?
请问在哪可以申请 长期订阅的自定义消息模板?
2023-02-23 - 多个小程序公用组件,模块的开发,引用和多个小程序的项目管理
* 有没有多个小程序的项目管理案例,主要是关于多个小程序公共组件的的开发,维护和项目组织结构 比如我现在有有三个小程序。都是有新增地址模块。 做成第三方组件导入进去。那么这个第三方组件该放在哪里。 我可能比较不清楚的是多个小程序管理的项目目录结构中它们公用模块的安放 有项目结构截图的最好啦,3q
2018-02-27 - 微信人脸核身接口能力
一、能力背景 近年来,国家在医疗挂号、APP注册、快递收寄、客运、运营商等多领域规定,需要用户实名才可办理业务,预计后续也会有越来越多的此类法规。因此,微信参照公安部“互联网+”可信身份认证服务平台标准,依托腾讯公司及微信的生物识别技术,建立微信“实名实人信息校验能力” ,即通过人脸识别+权威源比对,校验用户实名信息和本人操作(简称微信人脸核身)。 目前接口限定主体及行业类目开放公测,提供给资质符合要求的业务方,在合适的业务场景内使用。目前仅支持持二代身份证的大陆居民。 由于人脸核身功能涉及到用户的敏感、隐私信息,因此调用此接口的小程序,需要满足一定的条件。即:小程序的主体以及类目,需要在限定的类目范围内,且与小程序的业务场景一致。开展的业务也需要是国家相关法规、政策规定的需要“实名办理”的相关业务(其他未在范围内的业务,则暂不支持)。 以下为接口接入及开发的详细内容。如开发中遇到任何疑问,可以点击此处通过社区反馈,将有工作人员跟进回复。 文档第四部分【再次获取核验结果api】,有助于提高业务方安全性,请务必接入! 现阶段微信人脸核验能力,针对小程序,开放的主体类目范围包含: 小程序一级类目 小程序二级类目 小程序三级类目 使用人脸核验接口所需资质 物流服务 收件/派件 / 《快递业务经营许可证》 物流服务 货物运输 / 《道路运输经营许可证》(经营范围需含网络货运) 教育 学历教育(学校) / (2选1):1、公立学校:由教育行政部门出具的审批设立证明 或 《事业单位法人证书》;2、私立学校:《民办学校办学许可证》与《民办非企业单位登记证书》 医疗 公立医疗机构 / 《医疗机构执业许可证》与《事业单位法人证书》 医疗 互联网医院 / 仅支持公立医疗机构互联网医院(2选1):1、卫生健康部门的《设置医疗机构批准书》;2、 《医疗机构执业许可证》(范围均需含“互联网诊疗”或名称含“互联网医院”等相关内容 医疗服务 三级私立医疗机构 / 仅支持三级以上私立医疗机构,提供《医疗机构执业许可证》、《营业执照》及《医院等级证书》 政务民生 所有二级类目 / 仅支持政府/事业单位,提供《组织机构代码证》或《统一社会信用代码证》。 金融业 银行 / (2选1):1、《金融许可证》; 2、《金融机构许可证》。 金融业 信托 / (2选1):1、《金融许可证》; 2、《金融机构许可证》。 金融业 公募基金 / (4选1):1、《经营证券期货业务许可证》且业务范围必须包含“基金”;2、《基金托管业务许可证》; 3、《基金销售业务资格证书》;4、《基金管理资格证书》。 金融业 证券/期货 / 《经营证券期货业务许可证》 金融业 保险 / (8选1):1、《保险公司法人许可证》;2、《经营保险业务许可证》;3、《保险营销服务许可证》;4、《保险中介许可证》;5、《经营保险经纪业务许可证》;6、《经营保险公估业务许可证》或《经营保险公估业务备案》;7、《经营保险资产管理业务许可证》 ;8、《保险兼业代理业务许可证》。 金融业 消费金融 / 银监会核准开业的审批文件与《金融许可证》与《营业执照》。 金融业 非金融机构自营小额贷款 / 仅支持省金融办监管的网络小贷主体,同时提供:1、《小额贷款公司经营许可证》或《小额贷款机构经营许可证》或省金融办批准文件;2、申请主体资质承诺函。 金融业 汽车金融/金融租赁 / 仅支持汽车金融/金融租赁主体,同时提供:1、《营业执照》(公司名称包含“汽车金融” /“金融租赁”;营业范围包含“汽车金融”/“金融租赁”业务);2、《金融许可证》或银保监会及其派出机构颁发的开业核准批复文件。 交通服务 网约车 快车/专车/其他网约车 (自营性网约车)提供《网络预约出租汽车经营许可证》。(网约车平台)提供与网约车公司的合作协议以及合作网约车公司的《网络预约出租汽车经营许可证》。 交通服务 航司服务 / 提供《公共航空运输企业经营许可证》 交通服务 机场服务 / 提供《民用机场使用许可证》或《运输机场使用许可证》 交通服务 公交/地铁 / 提供公交/地铁/交通卡公司《营业执照》 交通服务 水运 / (船企)提供《水路运输许可证》。(港口)提供《港口经营许可证》 交通服务 骑车 / 仅支持共享单车,提供共享单车公司《营业执照》 交通服务 火车/高铁/动车 / 仅支持铁路局/公司官方,提供铁路局/公司《营业执照》 交通服务 长途汽车 / (2选1):1、《道路运输经营许可证》(经营范围需含客运);2、官方指定联网售票平台(授权或协议或公开可查询文件)。 交通服务 租车 / 运营公司提供《备案证明》与对应公司《营业执照》,且营业执照中包含汽车租赁业务 交通服务 高速服务 / 仅支持ETC发行业务,(2选1):1、事业单位主体,需提供《事业单位法人证书》;2、官方指定的发行单位(一发单位),需提供“官方授权或协议,或公开可查询的文件”; 生活服务 生活缴费 / (供电类)提供《电力业务许可证》与《营业执照》,且《营业执照》且经营范围含供电。(燃气类)提供《燃气经营许可证》与《营业执照》,且《营业执照》且经营范围含供气。(供水类)提供《卫生许可证》与《营业执照》。(供热类)提供《供热经营许可证》与《营业执照》,且《营业执照》且经营范围含供热。 IT科技 基础电信运营商 / (2选1):1、基础电信运营商:提供《基础电信业务经营许可证》;2、运营商分/子公司:提供营业执照(含相关业务范围)。 IT科技 转售移动通信(中国移动) / 仅支持虚拟运营商,同时提供:1、《营业执照》;2、《增值电信业务经营许可证》(业务种类包含“通过转售方式提供的蜂窝移动通信业务”或“含在全国转售中国移动的蜂窝移动通信业务”);3、虚拟运营商与基础电信运营商签订的合作协议或授权文件;4、所在地省级通信管理局向虚拟运营商颁发的网络渠道编码 IT科技 转售移动通信(中国联通) / 仅支持虚拟运营商,同时提供:1、《营业执照》;2、《增值电信业务经营许可证》(业务种类包含“通过转售方式提供的蜂窝移动通信业务”或 “含在全国转售中国联通的蜂窝移动通信业务”);3、虚拟运营商与基础电信运营商签订的合作协议或授权文件;4、所在地省级通信管理局向虚拟运营商颁发的网络渠道编码 IT科技 转售移动通信(中国电信) / 仅支持虚拟运营商,同时提供:1、《营业执照》;2、《增值电信业务经营许可证》(业务种类包含“通过转售方式提供的蜂窝移动通信业务”或“含在全国转售中国电信的蜂窝移动通信业务”);3、虚拟运营商与基础电信运营商签订的合作协议或授权文件;4、所在地省级通信管理局向虚拟运营商颁发的网络渠道编码 IT科技 转售移动通信(中国广电) / 仅支持虚拟运营商,同时提供:1、《营业执照》;2、《增值电信业务经营许可证》(业务种类包含“通过转售方式提供的蜂窝移动通信业务”或“含在全国转售中国广电的蜂窝移动通信业务”);3、虚拟运营商与基础电信运营商签订的合作协议或授权文件;4、所在地省级通信管理局向虚拟运营商颁发的网络渠道编码 旅游服务 住宿服务 / 仅支持酒店,提供《酒店业特种行业经营许可证》 旅游服务 旅游管理单位 / 仅支持政府/事业单位,提供《组织机构代码证》或《统一社会信用代码证》 商业服务 公证 / 仅支持公证处,提供《公证处执业许可证》或《事业单位法人证书》 社交 直播 / (2选1):1、《信息网络传播视听节目许可证》;2、《网络文化经营许可证》(经营范围含网络表演)。 如对以上类目或资质有疑问,可点击参考小程序“非个人主体开放的服务类目”,详细了解小程序开放的服务类目及对应资质。 二、准备接入 (请在小程序发布后,再提交人脸核身接口申请) 满足第一节中描述的类目和主体的小程序,可申请微信人脸核验接口。目前微信人脸核身接口已改为线上自助申请方式,需按照如下图例指引,进行接口申请: 第一步:请通过mp.weixin.qq.com登录小程序账号在后台“功能-人脸核身”的路径,点击开通按钮—— [图片] 第二步:仔细查阅《人脸识别身份信息验证服务条款》后,点击“同意并下一步”—— [图片] 第三步:请正确填写服务信息,并上传该小程序类目下所要求的资质—— [图片] 第四步:请按照业务实际需求填写使用人脸接口的场景和用途—— [图片] 第五步:请完善测试信息和联系人—— [图片] 第六步:提交后请耐心等待1-3个工作日的审核期,审核结果将以站内信通知—— 如申请期间遇到问题,可联系腾讯工作邮箱 wx_city@tencent.com,将会有相关工作人员进一步指引。 三、接口文档: (一)接口描述 名称: wx.startFacialRecognitionVerify(OBJECT) 功能:请求进行基于生物识别的人脸核身 验证方式:在线验证 兼容版本: 一闪:android 微信7.0.22以上版本, iOS 微信7.0.18以上版本 建议在微信官网升级至最新版本 (二)参数说明 1、OBJECT参数说明: 参数 类型 必填 说明 name String 是 姓名 idCardNumber String 是 身份证号码 success Function 否 调用成功回调 fail Function 否 调用失败回调 complete Function 是 调用完成回调(成功或失败都会回调) 2、CALLBACK返回参数 参数 类型 说明 errMsg String 错误信息 errCode Number 错误码 verifyResult String 本次认证结果凭据,第三方可以选择根据这个凭据获取相关信息 注 1:传递用户姓名和身份证有两种方式 业务方没有用户实名信息,用户需要在前端填写身份证和姓名,那么前端直接通过jsapi 调用传递 name 和 idCardNumber。 业务方已经有用户实名信息,后台通过微信提供的 api(详情见文档后面“上传姓名身份证后台 api”)上传用户身份证姓名和身份证,api 返回 user_id_key 作为凭证传给前端,前端再调用 jsapi,用户姓名、身份证信息不需要经过前端,参数只需要传递 userIdKey。Tips:使用该功能需要小程序基础库版本号>=1.9.3。 3、回调结果说明 回调结果请参考以下释义: [图片] [图片] [图片] 4、示例代码 [图片] [图片] (三)上传用户姓名身份证的后台api 1、API说明 1.1说明 业务方上传用户姓名和身份证,获取用户凭证,把凭证给到前端通过 jsapi 调用。 Tips :使用该功能需要小程序基础库版本号>=1.9.3。 1.2请求URL https://api.weixin.qq.com/cityservice/face/identify/getuseridkey?access_token={ac cess_token} 1.3请求方式 POST 2、请求数据格式 [代码]Json { "name" : “张三”, "id_card_number" : "452122xxxxxxx43215" } [代码] 请求示例 [代码]#!/bin/bash TOKEN='xxxxxxxxxxxx' URL='https://api.weixin.qq.com/cityservice/face/identify/getuseridkey' JSON='{ "name": "张三", "id_card_number": "452344xxxxxxxxxxxxx234"}' curl "${URL}?access_token=${TOKEN}" -d "${JSON}" [代码] 参数说明 json 字段 中文显示 是否必传 name 姓名 是 id_card_number 身份证号码 是 out_seq_no 业务方唯一流水号 否 3、返回数据 参数 类 型 说明 errcode int 错误码 errmsg string 错误信息 user_id_key string 用于后台交互表示用户姓名、身份证的凭证 expires_in uint32 user_id_key 有效期,过期需重新获取 [代码]{ "errcode" : 0, "errmsg" : "ok", "user_id_key" : "id_key_xxxx", "expires_in": 3600 } [代码] 4、后台消息推送 如果业务方传入out_seq_no,核身完成后会通过消息推送回调给业务方的服务器,如果回调业务方失败,会在5s尽力推送,超过5s不再推送。 参数说明 参数 类 型 说明 ToUserName string 小程序原始ID FromUserName string 事件消息openid CreateTime uint32 消息推送时间 MsgType string 消息类型 Event string 事件类型 openid string 核身用户的openid out_seq_no string 业务方唯一流水号 verify_result string 核身返回的加密key(凭据) 返回示例 [代码]{ "ToUserName": "gh_81fxxxxxxxx", "FromUserName": "oRRn15NUibBxxxxxxxxx", "CreateTime": 1703657835, "MsgType": "event", "Event": "face_identify", "openid": "oRRn15NUibBxxxxxxxxx", "out_seq_no": "test1234", "verify_result": "XXIzTtMqCxwOaawoE91-VNGAC3v1j9MP-5fZJxv0fYT4aGezzvYlUb-n6RWQa7XeJpQo0teKj8mGE4ZcRe1JI3GqzADBYORBu613rKjKAFfEXTXw_bu1bs7MnmPOpguS" } [代码] 四、再次获取核验结果api 此接口是前端完成人脸核身后,基于前端返回的凭据,通过后台api再次进行核验结果和身份信息的校验,有助于提高安全性,请务必接入! 前端获取结果不可信,存在被篡改的风险,为了保障请求结果安全性,请务必对identify_ret、id_card_number_md5、name_utf8_md5字段进行校验! (一)API说明 1、说明 人脸核身之后,开发者可以根据jsapi返回的verify_result向后台拉取当次认证的结果信息。 2、请求URL https://api.weixin.qq.com/cityservice/face/identify/getinfo?access_token={access_token} 3、请求方式 POST 4、请求格式 json (二)请求数据说明 1、请求 参数 类型 是否必填 描述 verify_result String 是 jsapi返回的加密key(凭据) 2、数据返回 HTTP 头如下 Date: Mon, 06 Feb 2017 08:12:58 GMT Content-Type: application/json; encoding=utf-8 Content-Length: 85 Connection: close json示例 [代码]{ "errcode" : 0, [代码] [代码]"errmsg" : "ok", "identify_ret" : 0, "identify_time" : 1486350357 "validate_data": "8593" [代码] [图片] (三)返回参数说明 1、返回参数 注:errcode和identify_ret同时为0,代表本次认证成功。 参数 类型 描述 errcode int 错误码, 0表示本次api调用成功 errmsg string 本次api调用的错误信息 identify_ret int 人脸核身最终认证结果 identify_time uint32 认证时间 validate_data string 用户读的数字(如是读数字) openid string 用户openid user_id_key string 用于后台交互表示用户姓名、身份证的凭证 finish_time uint32 认证结束时间 id_card_number_md5 string 身份证号的md5(最后一位X为大写) name_utf8_md5 string 姓名MD5 2、错误码对应信息 errcode 备注 84001 非法identity_id 84002 用户信息过期 84003 用户信息不存在 五、小程序辅助接口:检查设备是否支持人脸检测 1、接口名称 接 口 :wx.checkIsSupportFacialRecognition(OBJECT) 功能:检查设备是否支持人脸检测 2、接口说明和使用 小程序调用该接口,可以检测当前手机设备是否具备支持人脸检测的能力,可与以上接口分开使用,为了用户体验,建议调用后对手机设备不支持的用户做对应功能处理。 3、接口说明和使用 01 OBJECT 参数说明: 参数 类型 是否必填 描述 success Function 否 调用成功回调 fail Function 否 调用失败回调 complete Function 是 调用完成回调(成功或失败都会回调) checkAliveType Number 否 人脸核验的交互方式,默认读数字(见表 2) 表 2:checkAliveType 的值和对应的解释: 参数 解释 2 先检查是否可以屏幕闪烁,不可以则自动为读数字 02 CALLBACK 返回参数 参数 类型 说明 errMsg Boolean 错误信息 errCode Number 错误码 03 回调结果说明 回调类型 ErrCode 说明 sucess 0 支持人脸采集 fail 10001 不支持人脸采集:设备没有前置摄像头 fail 10002 不支持人脸采集:没有下载到必要模型 fail 10003 不支持人脸采集:后台控制不支持 回调结果说明仅对Android生效,iOS不返回errcode。 04 示例代码 [图片] 六、安全性说明 为保障业务可用性以及安全性,请详细研读微信人脸核身接口相关基础说明及安全说明文档:https://docs.qq.com/doc/DTFB0YWFIdGV6amly 备注:如开发中遇到任何疑问,可以点击此处通过社区反馈,将有工作人员跟进回复。 七、案例展示及补充说明 安徽医科大学第二附属医院,微信人脸核验登录: 安徽医科大学第二附属医院,是三级甲等综合医院。其小程序为用户提供挂号、门诊费用、住院费用、检查报告、体检等医疗服务,同时也提供停车、餐饮等便民服务,是医疗小程序中完整的案例。 小程序使用了微信人脸核验能力作为登录的核验。满足医院管理要求,也满足国家对于实名就医的管理规则。 案例实现的截图效果如下: [图片] [图片] 针对近期少数小程序方面反馈的两类问题,也在本课程进行补充说明。 1、本接口的开放范围,即:可支持的主体类目,是否可以扩大? 说明:基于本接口整体使用范围的评估、相关法规的参考、监管策略的理解执行等,暂时未立刻进行扩大开放范围的工作。 但我们会持续基于不同行业的法规、政策及监管要求等,逐一进行研究考量,以便确认如何扩大开放范围。 2、小程序如果涉及用户本人的生物特征采集,(如本人人脸照片、人脸视频),或涉及采集用户本人生物特征信息并开展人脸核验功能,则存在被驳回的情况? 说明:近两年“人脸识别”技术在社会上掀起了热潮。人脸识别虽然作为摆脱“中间媒介”或“承载载体”的一种直接技术手段,解决了部分政务、交通、医疗、零售等证明“操作者是本人”的问题,但也因此,引入了新的更大的安全风险。 一是,虚假安全风险。 身份认证领域的安全三因素包括“我知道什么”、“我拥有什么”、“我的特征是什么”,通用的安全做法,是要双因素认证(2FA),人脸识别技术如仅凭“我的特征是什么”这一个因素,则容易被攻破或利用。表象给用户以安全的感觉,但实际并不能达到安全效果。 二是,信息泄漏的风险。 越来越多的组织或个人,在并非必需用户敏感信息、生物特征的情况下,采集并存储此类信息。在信息加密、传输、存储过程中,容易暴漏更多的网络节点,使得此类信息有更大的风险被网络黑客拦截、窃听、窃取,或直接被脱库。 三是,消除风险的难度大。 以往基于“中间媒介”或“承载载体”的方式,如出现丢失、被冒用、恶意盗用等风险,可以通过挂失、更换、使用新载体或新媒介等方式,快速排除一定的风险。C端主动,B端主动,都能解决一部分问题。但人脸识别做为更直接的方式,一旦出现冒用、盗用,受害者将面临更大的财产及人生安全风险,且C端用户更多时候无法主动消除风险。 基于以上问题风险,加之国家出台《网络安全法》、《用户隐私保护条例》等法律法规标准,网信办、公安部、工信部及市场监管总局等四部委发起的app获取隐私整治,结合平台安全、用户敏感隐私信息保护要求及监管,针对部分暂无相关法规或要求,需要采集或生物认证方式进行身份核验的,或以“追热点”或“尝鲜”为目的,采集用户生物特征或进行身份核验的,进行严格审核,必要时不予以支持。
10-17 - 微信小程序内嵌webview相关知识点整理
前言 随着微信小程序的广泛应用,越来越多的商家选择将营销阵营选择迁移到了小程序中,但受其小程序体积限制的影响,不能够完全满足商户的要求,应运而生的web-view组件很好的解决的这一问题。一方面内嵌web-view能够直接运行在小程序中,大大减少了商户的开发成本,另一方面能够实现小程序与h5的跳转,有良好的扩展性,方便商户多端间引流。 一、web-view内嵌h5与传统小程序对比 通过查找相关资料发现,内嵌web-view和微信小程序在离线能力、页面切换体验、二次渲染,操作响应和开发灵活性上有如下对比,在不同场景下可能性能上有些许出入,仅供参考。 [图片] 表格来源:https://segmentfault.com/a/1190000017752299 从上表中可以对比出 H5 相较于小程序的优缺点,开发者可以根据实际需要选择。此外,使用web-view还有以下优点: (1)己方账号(第三方)与小程序openId/UnionId的关联绑定,实现免登陆 比如你是某门户网站,需要识别自己小程序上的用户与网站用户的关系,可以通过三种方法绑定关系,公众号,小程序原生,小程序web-view内嵌跳转三种方法。 (2)内嵌H5的富文本,减少重复开发 比如你是门户网站,社区,以往有大量的新闻和帖子,里面带了各种css样式的富文本,音视频自定义的点击事件等,小程序的原生组件可能无法兼容,这时候直接内嵌这些H5新闻,将会大大降低开发成本。 (3)热更新,减少发布审核 内嵌H5可以减少频繁提交小程序审核,商户只需要重新发布h5的版本,就可以更新内嵌web-view的内容。 <script type="text/javascript" src='//res.wx.qq.com/open/js/jweixin-1.4.0.js'></script 3.4 web-view和小程序间通信 官方给出了两种通信方法。 1、postMessage 通信 在 H5 中需要先用 wx.miniProgram.postMessage 接口,把需要分享的信息,推送给小程序。 在用户点击了小程序后退、组件销毁、分享这些特殊事件之后,小程序页面通过 bindmessage 绑定的函数读取 post 信息。 2、设置 web-view 组件的 URL 通信 H5 跳转小程序: // h5中跳转小程序 navigateToWeixin() { wx.miniProgram.navigateTo({url: '/pages/shop/index'}); } // 小程序跳转h5--第一步 <view> <web-view src="{{url}}" ></web-view> </view> // 小程序跳转h5--第二步:在小程序的 js 文件中设置通过 URL 以问号传参的方式传入参数到 H5中 if(!option.page){ this.setData({ url: `${this.data.url}?${test}` }); } else { this.setData({ url: `${this.data.url}${option.page}?${test}` }); } 四、内嵌web-view调试解决方案 首先通过微信开发者工具打开,这里url本地调试可以跟局域网链接,开发者工具可以实时显示,如果跟的是线上链接,可能只能通过预览扫码。 [图片] 右键点击页面,左上角会出现调试,可以在右图的调试器中对h5进行调试。 [图片] 五、踩过的小坑 (1)H5唤醒一些小程序API有一定的延时,0.3~1秒; (2)请调用小程序专用的JSSDK,公众号中的JSSDK不通用; (3)web-view一定是撑满全屏的,自定义顶部菜单,悬浮的都没用; (4)web-view后边跟的h5链接,必须要url转义,否则会和小程序自身的符号定义冲突,可能识别不到?后的参数; (5)H5控制小程序的跳转路径必须是“/”开头,如 “/pages/xxx/xxx”,且路径必须在app.json里有,地址错误的话,有时不报错。 (6)postMessage的json必须是data开始,不然接收不到数据。 (7)bindmessage相关: 小程序后退:使用接口名 wx.miniProgram.navigateTo,wx.miniProgram.navigateBack,wx.miniProgram.switchTab 等切换小程序页面/场景的API时候都会触发。分享:这个就是当你点分享小程序的时候,会接受到H5之前发送的postMessage。组件销毁,web-view组件销毁,类似 wx.miniProgram.redirectTo 都会触发。(8)内嵌h5跳转小程序是有严重缓存的,比如:h5页面有计时器,跳转小程序后计时器依然会计时,可以通过在url后面加时间戳的方式解决。 还有小程序已经关闭,H5自带的背景音乐仍然在手机后台播放,可以通过浏览器标签页被隐藏或显示的时候会触发visibilitychange(页面可见性状态)事件解决。 六、总结 看到这里,相信大家对于内嵌web-view已经有了大致的了解,我们主要对内嵌web-view与传统小程序进行对比,分析了内嵌web-view的优缺点,其次对如何配置内嵌web-view进行了阐述,然后对实战中内嵌web-view如何调试进行了示例,最后对实战中可能踩坑和注意的小点进行了友情提示。所以如果本篇文章有帮助到你的话,小编会非常欣慰,欢迎点赞和转发呦~
2020-06-16 - 订阅消息长期订阅 能不能自定义模板?
我们公司是在,政务服务,税务下,做相关消息,但是官方提供的消息模板不太适合我们的业务场景,是否可以自定义模板呢?
2021-03-11 - 1.05.2201210版本工具新增代码质量面板,导致packOptions.ignore失效?
工具更新到版本1.05.2201240 ,上传代码时自动走代码质量分析面板,查看错误提示貌似把packOptions.ignore配置的images文件夹也算进了分包大小,导致上传和预览失败 [图片] [图片] 查阅工具版本更新说明,发现1.05.2201210版本新增了代码质量分析面板 [图片] 将工具版本回退到以上版本(1.05.2201210)之前,发现可以成功上传和预览 [图片] 自测以下4个版本上传和预览效果: 1.05.2201210之后版本:1.05.2203070、1.05.2201240 上传失败 1.05.2201210之前版本:1.05.2110110、1.05.2108150 上传成功 所以现在怀疑是不是新增代码质量分析面板后导致packOptions.ignore失效,从而上传和预览失败
2022-04-10 - 消息推送配置提交时:一直提示:请求超时,请检查信息是否填写正确?
AppID(小程序ID): wxf56aec5c5272f48f url: https://api.oskysoft.com/OskyShop/ 接口程序有跟踪日志,没有收到微信服务器发送过来的echostr的请求信息。
2022-02-24 - 消息推送url配置问题-请求超时,请检查信息是否填写正确?
url 配置 : https://www.jsomega.top/jfgl/openPushMsg 地址试了可以访问的,消息配置一直报错请求超时,后台日志没有收到请求
2021-07-06 - 小程序的消息推送配置好后,URL(服务器地址)配置的后台程序接收不到请求,提示Token校验失败?
URL(服务器地址)的配置是:http://xxxxxxx/request.php 具体配置如下: [图片] 但是提交后,request.php没有接收到任何请求,request.php中的打印日志也没有执行,急需求解!! 测试程序是这样的: ob_clean() printLog(json_encode($_GET)); /** * 打印数据 * @param string $txt 日志记录 * @param string $file 日志目录 * @return */ function printLog($txt="",$file="ceshi.log"){ $myfile = fopen($file, "a+"); $StringTxt = "[".date("Y-m-d H:i:s")."]".$txt."\n"; fwrite($myfile, $StringTxt); fclose($myfile); } 我换成CURL去发送GET请求这个地址http://xxxxxxx/request.php,是可以打印日志的,postman也是可以的,有大神指点迷津吗?
2021-07-30 - 配置中packOptions ignore没有生效?
版本号: RC 1.05.2203251 ,Windows 11系统和Windows 10 系统均出现 上传体验版本,报体积超限。 [图片] project.config.json 已经加入了如下配置: "packOptions": { "ignore": [ { "value": "images", "type": "folder" } ], "include": [] }, 下图是上面报错后,点击“查看文件列表” [图片] 然后尝试回退到上一个稳定版本(1.05.2201240), 就可以正常上传。 现在怀疑是IDE的bug,导致ignore配置没有生效。帮忙解决一下。
2022-04-06