- picker在PC点击无反应?
win10,在电脑版版3.6.0.18版本下,picker组件可以正常使用,微信版本更新为最新的3.9.10.19之后,picker组件点击之后无反应,没有弹窗出来 [图片]
2024-04-28 - 报告一个setData的bug
https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html 代码片段:https://developers.weixin.qq.com/s/Id8krNmn7BQZ 步骤1:页面中,在data里用new Array()方法创建一个空数组,数组的元素预期是对象 步骤2:将此数组用wx:for属性绑定到页面上,显示数组中元素的某个属性 步骤3:在onload函数中创建一个局部变量数组,数组的元素是对象,创建完成后,将局部数组setData给data里面的空数组,此时页面能够正常显示 步骤4:页面显示数组元素属性的区域用bindtap属性,添加一个点击响应函数, 步骤5:点击后,能够进入响应函数,在点击响应函数中用setData方法修改属性的值,不成功,全局数组没有被修改成功,页面也没有更新显示
2024-04-28 - 小程序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 - 小程序页面通信、数据刷新、事件总线 、event bus 终极解决方案之 iny-bus
#### 背景介绍 在各种小程序中,我们经常会遇到 这种情况 有一个 列表,点击列表中的一项进入详情,详情有个按钮,删除了这一项,这个时候当用户返回到列表页时, 发现列表中的这一项依然存在,这种情况,就是一个 `bug`,也就是数据不同步问题,这个时候测试小姐姐 肯定会找你,让你解决,这个时候,你也许会很快速的解决,但过一会儿,测试小姐姐又来找你说,我打开了 四五个页面更改了用户状态,但我一层一层返回到首页,发现有好几个页面数据没有刷新,也是一个 bug, 这个时候你就犯愁了,怎么解决,常规方法有下面几种 #### 解决方法 1. 将所有请求放到 生命周期 `onShow` 中,只要我们页面重新显示,就会重新请求,数据也会刷新 2. 通过用 `getCurrentPages` 获取页面栈,然后找到对应的 页面实例,调用实例方法,去刷新数据 3. 通过设置一个全局变量,例如 App.globalData.xxx,通过改变这个变量的值,然后在对应 onShow 中检查,如果值已改变,刷新数据 4. 在打开详情页时,使用 redirectTo 而不是 navigateTo,这样在打开新的页面时,会销毁当前页面, 返回时就不会回到这个里面,自然也不会有数据不同步问题 #### 存在的问题 1. 假如我们将 所有 请求放到 onShow 生命周期中,自然能解决所有数据刷新问题,但是 onShow 这个生命周期,有两个问题 第一个问题,它其实是在 onLoad 后面执行的,也就是说,假如请求耗时相同,从它发起请求到页面渲染, 会比 onLoad 慢 第二个问题,那就是页面隐藏、调用微信分享、锁频等等都会触发执行,请求放置于 `onShow` 中就会造成 大量不需要的请求,造成服务器压力,多余的资源浪费、也会造成用户体验不好的问题 2. 通过 `getCurrentPages` 获取页面栈,然后找到对应的 页面实例,调用实例方法,去刷新数据,这也 不失为一个办法,但是就如微信官方文档所说 > 不要尝试修改页面栈,会导致路由以及页面状态错误。 > 不要在 App.onLaunch 的时候调用 `getCurrentPages()`,此时 page 还没有生成。 同时、当需要通信的页面有两个、三个、多个呢,这里去使用 `getCurrentPages` 就会比较困难、繁琐 3. 通过设置全局变量的方法,当需要使用的地方比较少时,可以接受,当使用的地方多的时候,维护起来 就会很困难,代码过于臃肿,也会有很多问题 4. 使用 redirectTo 而不是 navigateTo,从用来体验来说,很糟糕,并且只存在一个页面,对于 tab 页面,它也无能为力,不推荐使用 #### 最佳实践 在 Vue 中, 可以通过 new Vue() 来实现一个 event bus作为事件总线,来达到事件通知的功能,在各大 框架中,也有自身的事件机制实现,那么我们完全可以通过同样的方法,实现一个事件中心,来管理我们的事件, 同时,解决我们的问题。iny-bus 就是这样一个及其轻量的事件库,使用 typescript 编写,100% 测试覆 盖率,能运行 js 的环境,就能使用 传送门 [源码](https://github.com/landluck/iny-bus) [NPM](https://www.npmjs.com/package/iny-bus) [文档](https://landluck.github.io/iny-bus/docs/) #### 简单使用 iny-bus 使用及其简单,在需要的页面 onLoad 中添加事件监听, 在需要触发事件的地方派发事件,使监 听该事件的每个页面执行处理函数,达到通信和刷新数据的目的,在小程序中的使用可以参考以下代码 [代码] // 小程序[代码] [代码] import bus from [代码][代码]'iny-bus'[代码] [代码] // 添加事件监听[代码] [代码] // 在 onLoad 中注册, 避免在 onShow 中使用[代码] [代码] onLoad () {[代码] [代码] this[代码][代码].eventId = bus.on([代码][代码]'事件名'[代码][代码], (a, b, c, d) => {[代码] [代码] // 支持多参数[代码] [代码] console.log(a, b, c, d)[代码] [代码] this[代码][代码].setData({ a [代码]}) [代码] // 调用页面请求函数,刷新数据[代码] [代码] this[代码][代码].refreshPageData()[代码] [代码] })[代码] [代码] // 添加只需要执行一次的 事件监听[代码] [代码] this[代码][代码].eventIdOnce = bus.once([代码][代码]'事件名'[代码][代码], () => {[代码] [代码] // do some thing[代码] [代码] })[代码] [代码] }[代码] [代码] // 移除事件监听,该函数有两个参数,第二个事件id不传,会移除整个事件监听,传入ID,会移除该[代码] [代码] // 页面的事件监听,避免多余资源浪费, 在添加事件监[代码][代码]/// 听后,页面卸载(onUnload)时建议移除[代码] [代码] onUnload () {[代码] [代码] bus.remove([代码][代码]'事件名'[代码][代码], [代码][代码]this[代码][代码].eventId)[代码] [代码] }[代码] [代码] // 派发事件,触发事件监听处更新视图[代码] [代码] // 支持多参传递[代码] [代码] onClick () {[代码] [代码] bus.emit([代码][代码]'事件名'[代码][代码], a, b, c)[代码] [代码] }[代码] 更详细的使用和例子可以参考 [Github iny-bus 小程序代码](https://github.com/landluck/iny-bus/tree/master/examples) #### iny-bus 具体实现 * 基本打包工具,这里使用非常优秀的开源库 [typescript-library-starter](https://github.com/alexjoverm/typescript-library-starter),具体细节不展开 * 测试工具 使用 facebook 的 [jest](https://github.com/facebook/jest) * build ci 使用 [travis-ci](https://www.travis-ci.org/) * 测试覆盖率上传使用 [codecov](https://codecov.io/) * 具体的其他细节大家可以看源码中的 [package.json](https://github.com/landluck/iny-bus/blob/master/package.json),这里就一一展开讲了 iny-bus 的核心代码,其实就这么多,总的来说,非常少,但是能解决我们在小程序中遇到的大量 通信 和 数据刷新问题,是采用 各大平台小程序 原生开发时,页面通信的不二之选,同时,100% 的测试覆盖率,确保了 iny-bus 在使用中的稳定性和安全性,当然,每个库都是从简单走向复杂,功能慢慢完善,如果 大家在使用或者源码中发现了bug或者可以优化的点,欢迎大家提 pr 或者直接联系我 最后,如果 iny-bus 给你提供了帮助或者让你有任何收获,请给 作者 点个赞,感谢大家 [点赞](https://github.com/landluck/iny-bus)
2019-08-04