- 小程序服务商年度有奖调研开启
2022年是小程序发展的第六个年头,感谢服务商伙伴们陪伴小程序一起成长。 为更好地了解小程序第三方服务商的现状、帮助生态伙伴更好的发展,我们向您发起官方年度问卷调研。 希望您畅所欲言,您的体验、您的需求、您的痛点、甚至您的吐槽,我们都想知道。 调研时间:即日起至2022年3月16日 调研对象:微信小程序服务商 参与方式:点击小程序服务商年度官方调研填写调研问卷 [图片] *图片仅供参考,实际奖品选择与发放将视官方周边更新与存货情况进行适当调整* 问卷停止收集后,我们将从有效问卷中随机抽取100位参与者送出微信官方周边礼品。突出贡献回答者更有机会获得特别礼物及参与专享沙龙。 获奖名单将于3月30日在「小程序服务商官方交流群」进行公示,请服务商提交问卷后扫码进群,我们将会以短信通知得奖者确定邮寄地址。
2022-03-08 - 三方平台公众号授权报错?
公众号 wx75b322e4f8d36035 三方平台 wx6193b9e03898b565 [图片]
2021-09-10 - 三方平台,授权出现错误?
{"errcode":40094,"errmsg":"invalid component credential, rid: 6131bc6c-14db1561-61a3b4d5"} 平台appid:wx6193b9e03898b565
2021-09-08 - 微信开放平台在没有做任务改变,报61003错误?
微信 GET 请求发生错误!错误代码:61003,说明:component is not authorized by this account, rid: 6114d1c8-4f9c1a5e-14787c68 下午一点多都还是可以访问的,3点开始就报这个错了。授权也是正常授权的,没有任务改变
2021-08-12 - 复制任意微信小程序页面路径
以下以微信小程序“虎牙直播”为例,演示如何复制微信小程序页面的路径。 1.进入小程序的“关于虎牙直播”页面 [图片] 2.点击右上角的“…”进入“更多资料”页面 [图片] [图片] [图片] 3.复制AppID:wx74767bf0b684f7d3 4.进入小程序后台输入appid并搜索,然后点下一步 [图片] 5.鼠标移动到“获取更多页面路径”,在弹出窗口输入当前登陆的小程序的任意开发者微信号,然后点击开启,出现顶部的“开启入口成功”就可以使用手机访问“虎牙直播”任意页面进行复制了 [图片] 6.某个直播间的页面路径:pages/main/liveRoom/index.html?anchorUid=1678113423&source=search[图片] PS:复制出来的页面路径在小程序里使用的时候记得删除 .html 才能正常访问。
2020-01-16 - 浅谈小程序路由的封装设计
微信官方提供了基础的路由能力,在日常的开发中虽已够用,但随着开发的深入,会遇到许多值得思考提炼的问题。本文将探讨作者在微信小程序(以下简称小程序)开发当中遇到的问题,以及解决方案设计。 参考“WHY-HOW-WHAT"黄金圈思维法则,首先讲述为什么小程序的路由需要封装设计,也就是存在哪些问题,需要封装处理? 存在的问题 路由跳转的路径与文件路径耦合 小程序的路由跳转使用的是真实文件路径,因此若文件的结构发生变化,必会影响到所有的页面的跳转路径。 笔者在实际开发中就遇到这个问题,以小程序分包举例。 小程序的分包是以文件夹为单位的。如果要将一系列的页面拆分成分包,则需要将这些文件移至同个目录之下,因此必然导致路由的跳转路径发生变更。如果此时路由跳转均是直接通过文件路径跳转的话,则需要全局改动,导致的工作量不少。 另外,当开发团队比较庞大时,不同的业务之间总会存在互相跳转的情况。当其中一个页面地址发生变更时,其他业务跳转到该页面的路径都需要手动变更。若此时通知不及时,或者遗漏了一些地方,导致跳转失败,终会酿成大错。 路由传参 目前小程序支持的传参方式,即通过跳转路径上的query查询参数。 通过query传参的问题,与在Web上URL传参是一致的,比如: query的参数长度有限 query只能传递可序列化的数据 导航前需手动序列化,到达目标页面后需反序列化 条件导航 在日常业务中,会存在一些页面需要一定条件才允许进入的。 举个例子,会员服务是一种很常见的能力,而会员中心的进入条件是: 该用户已经完成登录 该用户是本产品的会员 一般情况下,这有特定准入资格的页面的导航逻辑是这样的: [图片] 这种方式简单明了,但存在一个问题:需要每次跳转前主动判断,逻辑冗余以外,还可能被遗漏。 思路 由于小程序本身已提供了基础的路由导航能力,不像react、vue.js那样需要从底层进行封装,从而提供路由能力。但是,本质上小程序可以理解成类vue.js这样的框架,因此可以从vue.js的路由库vue-router上找到灵感,从而解决以上问题。 命名路由 使用 命名路由 的方式可以解决前文提及的跳转路径和文件真实路径耦合问题。 通过[代码]Map[代码]来映射 页面ID 和 页面地址,路由跳转时,仅能使用 页面ID 进行路由跳转。 下面以导航至首页举例: [代码]// before wx.switchTab('pages/home/index') // after router.go('home') [代码] 由于小程序有tab页面和普通页面之分,因此导航至tab页时需使用switchTab 细心的读者可能会发现上文使用了[代码]go[代码]方法,而不是[代码]switchTab[代码]。其实,具体哪些页面属于tab页面,在[代码]app.json[代码]已经明确配置。对于使用者来说,不需要关心跳转的页面是属于哪种类型,这些细节都应该统一在底层封装好。下面罗列[代码]Router[代码]与官方API的对应关系: [图片] Router API的设计原则是保持简单,以及尽量保持与web规范一致 传递参数 微信官方提供的query方式传参,若参数是普通数据类型(如[代码]Number[代码]、[代码]String[代码])时可以直接使用;但若是涉及到复杂数据类型(如[代码]Array[代码]、[代码]Object[代码])时,需要先做序列化处理,当数据较为庞大时,性能的损耗还是比较明显的。 因此,在内存上传递参数是比较便利且容易想到的办法。 利用数据字典,将[代码]页面ID[代码]作为[代码]key[代码]、传递的参数作为[代码]value[代码],写入[代码]Router[代码]的[代码]state[代码]: [代码]router.go = function(pageID, params) { // do something... router.state[pageID] = params } [代码] 在目标页面上,可以通过[代码]router.getParams()[代码]方法,获取传递的参数。 由于采用了命名路由的方式,可以使用[代码]页面ID[代码]作为[代码]key[代码],避免了使用跳转路径做[代码]key[代码]时,涉及到的绝对与相对路径问题。 条件导航 条件导航可以使用类似vue-router的导航守卫来解决问题。 由于路由的能力是微信官方提供的,因此无法像 vue-router 那样提供多类型的导航守卫,但仅有全局导航守卫也足够使用。 以下仍以“会员中心”的进入逻辑举例,并简要介绍实现思路: [图片] 其中,to和from目前是pageID,其实可以封装更多信息,以保证导航守卫可以尽可能拥有更多的信息。因此to可以理解成是即将进入的页面路由对象,而from则是当前正要离开的路由对象。 路由对象可以包含以下信息: [代码]pageID[代码]:页面ID [代码]path[代码]:页面ID对应的path [代码]params[代码]:传递的参数 [代码]query[代码]: URL的查询参数 配置信息 由前文提到的 命名路由 做法需要一个配置文件来关联[代码]页面ID[代码]与[代码]页面路径[代码]的关系。 页面的配置信息,则是使用[代码]router.config.js[代码]设置,然后通过构建工具编译转成[代码]app.json[代码]。 以下是[代码]route.config.js[代码]: [图片] 其中,跳转首页则是[代码]router.go('home')[代码];而跳转分包[代码]health[代码]的首页则是使用[代码]router.go('health.home')[代码] 通过以上的配置文件,使用构建工具转换成微信官方可识别的[代码]app.json[代码]配置: [图片] 辅助函数 在日常开发当中,经常会用到一些和路由相关的通用辅助函数,如获取当前页面,获取上个页面等。这些辅助函数都应该统一抽象封装,避免代码冗余。 [代码]router.utils = { getCurPage() { // 获取当前页面信息 let pages = getCurrentPages() let len = pages.length return pages[len - 1] }, getPrePage() {}, // 获取上个页面信息 getParams() {}, // 获取传递的参数 getPageID(path) {} // 通过path找到pageID } [代码] navigator组件 微信官方除了提供[代码]API[代码]用于导航以外,还提供了[代码]navigator[代码]组件。 另外还有[代码]functional-page-navigator[代码]是用于插件当中,不能在小程序包使用,因此本文暂且将其忽略。 由于[代码]navigator[代码]的跳转参数仍是使用[代码]path[代码],因此笔者将其进行二次封装,改造成可以通过[代码]pageID[代码]跳转: [图片] 总结 由于小程序相对比较封闭,因此在路由上能做的东西比较有限。 但路由又与许多概念有千丝万缕的关系。比如路由与文件结构关联,而文件结构又影响到分包的设计,环环相扣,影响到的地方则会越来越多。 因此,能提前看到本文提到的可能出现的问题,也许对后续的小程序开发有一定的参考意义。 另外,前文提到的很多问题,在早期开发,或者没有深入开发之前,都不会遇到。但是当你开始经历前文提到的那些问题时,往往此时的改造成本已经很大了。因此希望本文能给你带了一些启发,在早期规避这些问题,那本文的使命就达到了。
2020-06-15 - 小程序全局事件监听
代码片段 https://developers.weixin.qq.com/s/g0tZKYmj7OhD //全局存储 var event = {}; //接收消息 传入params={name:"string 监听事件名",success:"function 监听事件回调",tg:"当前页面或App.js 传入this即可"} const $on = function(params) { if (!params) { return false; } if (!params.name) { console.error("事件监听未设置名称 属性key=name"); return false; } if (!params.success) { console.error("事件监听未设置回调函数 属性key=success"); return false; } if (!params.tg) { console.error("事件监听未设置目标对象 属性key=tg"); return false; } if (event[params.name]) { var list = event[params.name]; list.push([params.tg, params.success]); } else { event[params.name] = [ [params.tg, params.success] ]; } pageStatus(params.tg); } //消息发送 传入{name:"string 发送消息事件名",data:"可选 可以是任意数据类型"} const $emit = function(params) { if (!params) { return false; } if (!params.name) { console.error("事件监听未设置名称 属性key=name"); return false; } if (event[params.name]) { var list = event[params.name]; list.forEach(item => { item[1].call(item[0], params.data); }) } } //移除监听 传入params={name:"string 监听事件名",tg:"当前页面或App.js 传入this即可"} //如未移除监听 页面onUnload时将会自动移除 const $remove = function(params) { if (!params) { return false; } if (!params.tg) { console.error("事件监听未设置目标对象 属性key=tg"); return false; } if (params.name && event[params.name]) { event[params.name] = event[params.name].filter(a => { return a[0] != params.tg; }) } else { for (let key in event) { event[key] = event[key].filter(a => { return a[0] != params.tg; }) } } } //页面onUnload触发监听 const pageStatus = function(self) { if (self["onUnload"]) { var s = self["onUnload"]; self["onUnload"] = function(a) { s.call(this, a); $remove({ tg: this }); } } else { self["onUnload"] = function() { $remove({ tg: this }); } } } exports.$on = $on; exports.$emit = $emit; exports.$remove = $remove; 此方法可挂载至全局getApp()调用 也可引入文件调用 写的不好 大家见谅
2020-06-09 - 小程序页面(Page)扩展,为所有页面添加公共的生命周期、事件处理等函数
背景 在小程序的原生开发中,页面中经常会用到一些公共方法,例如在页面onLoad中验证权限、所有页面都需要onShareAppMessage设置分享等 假设我们在编码时每个页面都写一遍,显然不是一个高级程序员会干的事情,太Low了。如果我们定义一个公共文件,导出这些公共方法,每个页面都引入,然后再生命周期或者事件处理函数中调用,虽然看起来很方便,但不够优雅,达不到我们最终的目的(偷懒)。 下面给大家介绍一种相对比较优雅的实现方式,扩展Page来实现以上的操作。 Page(页面) 需要传入的是一个 [代码]object[代码] 类型的参数,那么我们重载一个 [代码]Page[代码] 函数,将这个 [代码]object[代码] 参数拦截改掉就可以了,下面直接上代码。 实现 1、在根目录新建一个 [代码]page-extend.js[代码] 文件,公共的逻辑都写在这里面 [代码]/** * * Page扩展函数 * * @param {*} Page 原生Page */ const pageExtend = Page => { return object => { // 导出原生Page传入的object参数中的生命周期函数 // 由于命名冲突,所以将onLoad生命周期函数命名成了onLoaded const { onLoaded } = object // 公共的onLoad生命周期函数 object.onLoad = function (options) { // 在onLoad中执行的代码 ... // 执行onLoaded生命周期函数 if (typeof onLoaded === 'function') { onLoaded.call(this, options) } } // 公共的onShareAppMessage事件处理函数 object.onShareAppMessage = () => { return { title: '分享标题', imageUrl: '分享封面' } } return Page(object) } } // 获取原生Page const originalPage = Page // 定义一个新的Page,将原生Page传入Page扩展函数 Page = pageExtend(originalPage) [代码] 2、在 [代码]app.js[代码] 中引入 [代码]page-extend.js[代码] 文件 [代码]require('./page-extend') App({ // 其他代码 ... }) [代码] 代码片段 https://developers.weixin.qq.com/s/Cyx8iGmV7Ldp 本文内容及评论未经允许,禁止任何形式的转载与复制(代码可在程序中使用)
2019-12-24 - 2020-08-16