- 关于公众号自定义消息模板?
公众号发送10种模板消息,在公共模板里都没有,要怎么自定义吗?还是说只能申请公共模板,我看公共模板一个月也只能申请三次
2022-05-12 - URL Scheme 和 URL Link 优化公告
为了帮助开发者更好地为用户提供服务,降低开发者使用 URL Scheme 和 URL Link 的成本,自 2023 年 12 月 19 日起,微信团队将对 URL Scheme 和 URL Link 进行如下优化: 1、新增明文 URL Scheme,开发者无需调用接口可自行拼接并且生成明文 Scheme; 2、取消 URL Scheme 和 URL Link 打开端一人一链的限制,支持同一条链接被多名用户访问; 3、新增打开端限制:每个小程序每天 URL Scheme 和 URL Link 总打开次数上限为 300 万次。 一、新增明文 URL Scheme开发者无需调用平台接口,可自行根据如下格式拼接 appid 和 path 等参数,作为 URL Scheme 链接。 weixin://dl/business/?appid=*APPID*&path=*PATH*&query=*QUERY*&env_version=*ENV_VERSION* 其中各参数含义如下: [图片] 注意: 1、为保护开发者,通过明文 URL Scheme 拉起的小程序(页面)必须要提前在「小程序管理后台 -> 设置 -> 隐私与安全 -> 明文 scheme 拉起此小程序」中进行声明; 小程序:配置能够通过明文 scheme 进入的小程序页面[图片] 小游戏:打开开关即可通过明文 scheme 拉起小游戏[图片] 2、通过明文 URL Scheme 打开小程序的场景值为 1286; 3、明文 URL Scheme 不受每天 50 万次的生成量限制; 4、明文 URL Scheme 没有有效期的概念,可长期有效; 5、明文 URL Scheme 没有一人一链的打开限制,支持一条链接同时被多名用户访问。 二、原 URL Scheme 升级为加密 URL Scheme,并支持自行拼接参数目前已对外提供的 URL Scheme 能力平滑升级为加密 URL Scheme,取消一人一链的限制,支持开发者自行在链接后拼接参数*CUSTOM PARAMETER*。 注意:之前通过平台接口生成的 URL Scheme 可继续使用,链接自动可支持多人打开。 URL Scheme格式 weixin://dl/business/?t=*TICKET*&cq=*CUSTOM PARAMETER* 其中参数含义如下: [图片] 注意:加密 URL Scheme 打开小程序的场景值保持不变,仍为 1065。 三、原 URL Link 升级为加密 URL Link,并支持自行拼接参数目前已对外提供的 URL Link 能力平滑升级为加密 URL Link,取消一人一链的限制,支持开发者自行在链接后拼接参数*CUSTOM PARAMETER*。 注意:之前通过平台接口生成的 URL Link 可继续使用,链接自动可支持多人打开。 URL Link格式: https://wxaurl.cn/*TICKET*?cq=*CUSTOM PARAMETER* 其中参数含义如下: [图片] 注意:加密 URL Link 打开小程序的场景值保持不变,微信外打开的场景值为 1194;微信内打开会调整为开放标签打开小程序,场景值为 1167。 四、调用规则调整1、加密 URL Scheme 和 URL Link 取消一人一链,支持一条链接同时被多名用户访问,生效后之前生成的链接被多名用户访问时,不会再报错; 2、每个小程序每天能够生成加密 URL Scheme 和 URL Link 共计 50 万条的限制不变,额外增加每个小程序每天在微信外,能够通过链接打开小程序共计 300 万次的打开量限制,其中链接包括加密 URL Scheme、加密 URL Link 和明文 URL Scheme ;若链接打开小程序的次数超过 300 万次/天,则无法通过链接在微信外拉起小程序; 3、URL Scheme (加密和明文)和 URL Link (加密)仅支持非个人主体小程序使用; 4、注意事项:平台有安全策略防止开发者的链接被黑灰产大量打开,可能导致达到访问上限无法正常通过链接打开小程序的问题; 5、查询方式:开发者可复用现有的查询方式对 URL Scheme 和 URL Link 进行打开额度查询和链接状态查询。 [图片]
2023-12-19 - 关于小程序隐私保护指引设置的公告
为规范开发者的用户个人信息处理行为,保障用户的合法权益,自2023年9月15日起,对于涉及处理用户个人信息的小程序开发者,微信要求,仅当开发者主动向平台同步用户已阅读并同意了小程序的隐私保护指引等信息处理规则后,方可调用微信提供的隐私接口。 开发者首先需确定小程序是否涉及处理用户个人信息,如涉及,则需配置用户隐私授权弹窗,且仅有在平台《小程序用户隐私保护指引》中声明了所处理的用户个人信息,才可以调用平台提供的对应接口或组件。(隐私相关接口) 隐私协议设置整体流程参考下方指引: 一、设置《小程序用户隐私保护指引》 开发者需在「小程序管理后台」设置《小程序用户隐私保护指引》 [图片] [图片] 二、填写《小程序用户隐私保护指引》 [图片] 只有在指引中声明所处理的用户个人信息,才可以调用平台提供的对应接口或组件。若未声明,对应接口或组件将无法调用成功。隐私接口与对应的处理的用户个人信息关系可见:小程序用户隐私保护指引内容介绍 三、配置用户隐私授权弹窗 微信提供了wx.onNeedPrivacyAuthorization(function callback) 接口,意为用户触发了一个微信侧未记录过同意的隐私接口调用,开发者可通过响应该事件选择提示用户的时机。此外,微信还提供了 wx.requirePrivacyAuthorize(Object object) 接口,可用于模拟触发 onNeedPrivacyAuthorization 事件。 小程序开发者可自行设计提示方式与触发时机,详细文档可查看隐私协议开发指南。 仅有在指引中声明所处理的用户个人信息,才可以调用平台提供的对应接口或组件。若未声明,对应接口或组件将直接禁用。 [图片] (参考样例) 四、如要进行代码提审,开发者需先自行声明是否有采集用户隐私,如有,则需在提审页面-「用户隐私保护设置」选择“采集用户隐私” [图片]
2023-09-18 - 借助实时数据推送快速制作在线对战五子棋小游戏丨实战
1 项目概述 游戏开发,尤其是微信小游戏开发,是最近几年比较热门的话题。 本次「云开发」公开课,将通过实战「在线对战五子棋」,一步步带领大家,在不借助后端的情况下,利用「小程序 ✖ 云开发」,独立完成一款微信小游戏的开发与上线。 2 任务目标 根据项目初始框架,阅读教程的同时,逐步完成棋盘绘制、音乐播放、玩家对战、输赢判定等功能,最终实现一个可以快乐玩耍的在线对战五子棋。 在这个过程中,会了解到 Serverless 的一些概念,并且实际应用它们,比如:云数据库、云存储、云函数、增值能力。除了这些基本功能,还准备了更多的硬核概念与落地实践,比如:实时数据库、聚合搜索、权限控制。 完成开发后,上传并且设置为体验版,欢迎邀请更多人来体验。 3 准备工作 从 TencentCloudBase/tcb-game-gomoku 中下载代码到本地: [代码]git clone https://github.com/TencentCloudBase/cloudbase-examples.git cd /cloudbase-examples/minigame/tcb-demo-gomoku [代码] 切换课程专用的 [代码]minigame-study[代码] 分支: [代码]git checkout minigame-study [代码] 4 实战任务 4.1 创建云开发与小游戏环境 1、打开微信 IDE,点击左侧的小游戏,选择右侧的导入项目,导入之前下载的「在线对战五子棋」的目录,AppID 修改为你已经注册好的小游戏 AppID。 [图片] 2、进入后,点击上方的云开发按钮。如果之前没有开通过云开发,需要开通云开发,新开通的话需要等待 10 ~ 20 分钟。 [图片] 3、进入「云开发/数据库」,创建新的集合,新集合的名称是[代码]rooms[代码]。 [图片] 4、进入「云开发/存储」,点击“上传文件”。上传的内容是[代码]/static/[代码]下的[代码]bgm.mp3[代码] 和 [代码]fall.mp3[代码]。之后的代码中会通过云存储的接口,请求文件的临时 url,这样做的目的是减少用户首次进入游戏加载的静态资源。 [图片] 4.2 准备配置文件 创建配置文件: [代码]cp miniprogram/shared/config.example.js miniprogram/shared/config.js [代码] 将关键字段的信息,换成自己账号的信息即可: [图片] 4.3 创建云开发接口 打开 [代码]miniprogram/shared/cloud.js[代码],在里面初始化云开发能力,并且对外暴露云数据库以及聚合搜索的 API。 [图片] 4.4 获取云存储资源的链接 为了减少用户首屏加载的静态资源,音乐资源并没有放在[代码]miniprogram[代码]目录下,而是放在了云存储中,通过调用云存储的 api 接口,来返回静态资源的临时链接。 在 [代码]miniprogram/modules/music.js[代码]中,会调用资源接口,获取资源链接: [图片] [代码]getTempFileURL[代码]函数属于云开发相关,因此放在了 [代码]miniprogram/shared/cloud.js[代码]中。这里只需要临时链接[代码]tempFileURL[代码]属性,其它返回值直接过滤调即可。 为了方便外面调用,promise 内部不再用 reject 抛错。对于错误异常,返回空字符串。这样,加载失败的资源不会影响正常资源的加载和 Promise.all 中逻辑进行。 [图片] 4.5 游戏进入与身份判断 根据前面的流程图我们可以看到,游戏玩家的身份是分为 owner 与 player。它们的含义如下: owner:玩家进入游戏后,查找是否有空闲房间,如果不存在空闲房间,那么就会主动创建新的空闲房间。那么对于新创建的房间,玩家就是 owner。 player:玩家进入游戏后,查找是否有空闲房间,如果存在空闲房间,那么就加入空闲房间。那么对于空闲房间,玩家就是 player。 判断的依据就是 [代码]judgeIdentity[代码] 方法中,读取云数据库集合中的 rooms 的记录。如果存在多个空闲房间,需要选取创建时间最近的一个房间。因此,这里需要用到「聚合搜索」的逻辑。 聚合搜索的条件,在这里有 3 个: 标记人数的字段,是否为 1 创建时间倒叙排序 只选择 1 个 [图片] 4.6 创建新房间 在上述的身份判断函数逻辑中,如果聚合搜索查询的结果为空,说明没有空闲房间,玩家需要作为 owner 来创建新的房间,等待其它玩家加入。 创建房间的逻辑就是将约定好的字段,放进云数据库的记录中。这些字段有: roomid<[代码]String[代码]>: 6 位房间号,唯一 nextcolor<[代码]"white" | "black"[代码]>: 下一步是白棋/黑棋走 chessmen<[代码]String[代码]>: 编码后的棋盘数据 createTimestamp<[代码]String[代码]>: 记录创建时间戳,精确到 ms people<[代码]Number[代码]>: 房间人数 是的,你可能注意到了,这里需要保证 roomid 是不重复的。因此本地生成的随机 roomid,需要先调用云数据库的查询接口,检测是否存在。如果存在,那么递归调用,重新生成随机字符串。 [图片] 4.7 监听玩家进入 对于 owner 身份来说,除了要创建新房间,还需要在创建后监听 player 身份的玩家进入游戏。 对于 player 身份的玩家进入游戏后,会更新记录中的 people 字段(1 => 2)。这时候就需要利用「实时数据库」的功能,监听远程记录的 people 字段变化。 代码实现上,调用[代码]watch[代码]方法,并且传递[代码]onChange[代码]函数参数。一旦有任何风吹草动,都可以在[代码]onChange[代码]回调函数中获得。对于传递给回调函数的参数,有两个比较重要: docChanges<[代码]Array[代码]>: 数组中的每一项对应每条记录的变化类型,变化类型有 init、update、delete 等。 docs<[代码]Array[代码]>: 数组中的每一项对应每条记录的当前数据。 [图片] 4.8 越权更新字段 对于 player 身份来说,进入房间后,既不需要「创建新房间」,也不需要「监听玩家进入」。但需要更新记录的 people 字段。由于记录是由 owner 身份的玩家创建的,而云数据库只有以下 4 种权限: 所有用户可读,仅创建者可读写 仅创建者可读写 所有用户可读 所有用户不可读写 以上 4 种权限,并没有「所有用户可读写」。因此,对于越权读写的情况,需要通过调用云函数来以“管理员”的权限实现。在 [代码]cloudfunction[代码] 中创建 [代码]updateDoc[代码] 云函数,接收前端传来的 collection、docid、data 字段。对于 data 字段来说,就是数据记录的最新更新数据。 [图片] 在小游戏中,通过[代码]wx.cloud.callFunction[代码]来调用云函数。传入的 data 字段指明被调用的云函数,传入的 data 字段可以在云函数的回调函数的 event 参数中访问到(如上图所示)。 [图片] 4.9 落子更新逻辑 不论对于 player 还是 owner 身份,都需要处理落子的逻辑。落子逻辑中,下面的两种情况是属于无效落子: 点击位置已经有棋子 对方还未落子,目前依然处于等待情况 对于以上两种情况,处理的逻辑分别是: 棋盘状态保存在内部类中,调用落子的函数,会返回是否成功的字段标识 只有监听到远程棋盘更新后,才会打开本地的锁,允许落子;落子后,会重新上锁 [图片] 落子成功后,要在本地判断是否胜利。如果胜利,需要调用退出的逻辑。但无论是否胜利,都要将本地的最新状态更新到云端。 [图片] 4.10 监听远程棋盘更新 不论对于 player 还是 owner 身份的玩家,都需要监听远程棋盘的更新逻辑。当远程棋盘字段更新时,本地根据最新的棋盘状态,重绘整个棋盘。并且进行输赢判定,如果可以判定输赢,则退出游戏;否则,打开本地的锁,玩家可以落子。 因为不同身份均需要监听,因此这一块的监听逻辑可以复用。不同的是,两种身份的监听启动时间不一样。owner 身份需要等待 player 身份玩家进入游戏后才开启棋盘监听;player 身份是更新了 people 字段后,开启棋盘监听。 在监听逻辑中,需要判断远程更新的字段是否是 chessmen,这是通过前面提及的 dataType 来实现的。还徐哟啊判断记录中的 nextcolor 字段是否和本地的 color 一样,来决定是否打开本地的锁。 [图片] 如果上述的两个条件均满足,则执行更新本地棋盘、判定输赢、打开本地锁的逻辑。 [图片] 4.11 游戏结束与退出 每次需要判定输赢的地方,如果可以判定输赢,那么都会走到游戏退出逻辑。退出的逻辑分为 2 个部分,第 1 个是给用户提示,第 2 个是调用云函数清空记录。 第 1 个逻辑中用户提示,需要判定用户胜负状态: [图片] 第 2 个逻辑中清除记录的原因是为了方便调试,对于真正的业务场景,一般不会删除历史数据,方便问题定位。同时,这也是一个越权操作,需要调用云函数来实现。 [图片] 6. 课程完整源码 https://github.com/TencentCloudBase/cloudbase-examples/tree/master/minigame/tcb-demo-gomoku 7. 联系我们 更多云开发使用技巧及 Serverless 行业动态,扫码关注我们~ [图片]
02-19 - video-swiper短视频轮播,解决方案2(增加动态加载数据)
实现短视频小程序指定到某个视频开始轮播,方案1已经解析过,这里就不多说了,不懂的可以请移步到这里查看:https://developers.weixin.qq.com/community/develop/article/doc/000c2e0afc8cc8b2a96b36d665b413 这里主要讲的是,如何进行动态加载数据问题 第一步,在获取数据列表中加个条件判断,如果超过你设置的长度就算二次获取数据,进行数据切割加到将要预览的数组里面,代码如下(主要看条件判断,这里以10个数据为例): videoList: { type: Array, value: [], observer: function observer() { var newVal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; if (newVal.length) { newVal.map((item, index) => { return item.idxKey = index + 1; }); if (newVal.length<=10) { this._videoListChanged(newVal); } else { // 重点是这里的条件判断 // 防止当前数组被污染 let arr = JSON.parse(JSON.stringify(newVal)); // 去掉已有的数据 let nextArr = arr.splice(this.data.total); this.data.nextQueue.push(...nextArr); } this.setData({total: newVal.length}) } } } 第二步,在每次滑动视频时,判断下当前视频总数和剩下视频个数,满足条件即可请求加载数据,代码如下: // 判断总数据是否大于等于10,并且下滑剩下4个视频开始请求接口拿数据;这里大小可以根据自己需求修改 if (total>=10 && nextQueue.length < 5) { this.triggerEvent('UpdataVideo', {}); } 就加这两步,轻松完成一个短视频,从定位到某个视频开始播放,到数据没有时进行预加载视频。 有什么问题,欢迎随时咨询。 完整版代码片段:https://developers.weixin.qq.com/s/Ikk98ymm7tph
2021-04-14 - 关于解决video-swiper组件的几个坑
1.不能从第一个视频播放 解决思路:在获取到数据后拿到第一条数据使用unshift放到数组的第一条(笨办法) 2.播放不到最后一个视频 解决思路:这个问题会在视频长度为3、6、9、12、下会出现,以此类推,相信大家看到这个长度就会有解决办法了吧 3.在播放到最后会重复播放倒数第二条 解决思路:这个问题会在视频长度为4、7、10、13、下会出现,以此类推,一开始还给数组复制了那个是不算在这个长度里的,这个长度最好是从后端拿,下面就贴代码 由于时间原因,解释的不太详细,直接贴图了,研究过源码里的算法一看就懂了,希望能帮助到大家,觉得还行给个赞以示鼓励 [图片] animationfinish: function animationfinish(e) { var _data = this.data, _last = _data._last, _change = _data._change, curQueue = _data.curQueue, prevQueue = _data.prevQueue, nextQueue = _data.nextQueue, total = _data.total; var current = e.detail.current; var diff = current - _last; if (diff === 0) return; this.data._last = current; this.playCurrent(current); this.triggerEvent('change', { activeId: curQueue[current].id}); var direction = diff === 1 || diff === -2 ? 'up' : 'down'; if (direction === 'up') { //判断下面是否有视频 if (this.data._invalidDown === 0) { //当前索引 var change = (_change + 1) % 3; //加入下一个视频 var add = nextQueue.shift(); //移除上一个视频 var remove = curQueue[change]; if (add) { prevQueue.push(remove); curQueue[change] = add; this.data._change = change; if((total%3) === 0 && nextQueue.length === 0) { curQueue[3] = add } else if((total%3) === 1 && nextQueue.length === 0){ this.setData({ _pop : curQueue.pop() }) } } else { this.data._invalidUp += 1; } } else { this.data._invalidDown -= 1; } } if (direction === 'down') { if (this.data._invalidUp === 0) { var _change2 = _change; var _remove = curQueue[_change2]; var _add = prevQueue.pop(); if (_add) { curQueue[_change2] = _add; nextQueue.unshift(_remove); this.data._change = (_change2 - 1 + 3) % 3; } else { this.data._invalidDown += 1; } } else { if((total%3) === 0 && curQueue.length === 4) { curQueue.pop() } else if((total%3) === 1 && nextQueue.length === 0){ curQueue.push(this.data._pop); } this.data._invalidUp -= 1; } } var circular = true; if (nextQueue.length === 0 && current !== 0) { circular = false; } if (prevQueue.length === 0 && current !== 2) { circular = false; } this.setData({ curQueue: curQueue, circular: circular }); // console.log(1, curQueue) // console.log(2, prevQueue) // console.log(3, nextQueue) // console.log('--------------', _change) },
2020-07-24 - video-swiper-短视频轮播,解决方案及部分思路
这是一个官方的组件,但是不符合自己业务逻辑,几经修改,勉强适合使用。 本插件适合有限视频轮播,先说说组件思路: 1、组件是使用微信组件swiper来做动画切换; 2、video标签,官方提示尽量不要超过3个标签(同一个界面),虽然我不知道为什么,但是肯定和性能有关; 链接地址:https://developers.weixin.qq.com/community/develop/doc/000e4ef22583d8961919efb6b56009[图片] 3、视频轮播逻辑规律是:组件是使用三个swiper-item一直做无限滚动(好处就是不会造成过多的节点,性能好),看图:[图片]图的意思是滑动轮播的规律:箭头表示当前swiper滑动的位置,然后显示对应的视频,这样轮动排放的逻辑可以知道进可攻,退可守,不会出现上下滑播放顺序就乱了。 图片我们也可以发现,当视频数量刚好是3的倍数,不会有任何排放问题,但是如果是3的余数是1或者2时,那就出坑了,因为轮播swrper-item是固定三个的,所以修改的组件就是解决这个余数问题。 解决的思路是:当余数为1时,我们把当前swiper-item轮播变成4个轮播,当余数为2时,我们把当前swiper-item轮播变成2个轮播;这样就可以解决余数不为0的时候,但是有个特殊情况就是当视频刚好4个,应该直接全部swiper-item展示,无需其它逻辑处理。 // 下面的代码是官方没有的,自增核心代码 // 手势向上时处理逻辑 if ((total % 3) === 1 && nextQueue.length === 0) { let timers = new Date(); let addItem = JSON.parse(JSON.stringify(add)); addItem.idxKey = timers.getTime(); curQueue[3] = addItem; } else if ((total % 3) === 2 && nextQueue.length === 0) { let _pop = curQueue.pop(); this.setData({ _pop: _pop }) } // 手势向下时处理逻辑 if ((total % 3) === 1 && curQueue.length === 4) { curQueue.pop(); } else if ((total % 3) === 2 && nextQueue.length === 0) { curQueue.push(this.data._pop); } 这里有个坑就是视频自动播放,如果元素有两个渲染key是相同时,会造成视频点击两次才能播放;出现此问题主要发生在总数余1时会出现(即总是大于4以上,且总数余1,时,swiper-item出现四个时候会渲染两个相同的视频,导致key渲染相同)。 解决此问题:主要保证渲染的key是唯一的即可; if ((total % 3) === 1 && nextQueue.length === 0) { let timers = new Date(); let addItem = JSON.parse(JSON.stringify(add)); addItem.idxKey = timers.getTime(); // 此语句就是保证添加四个swiper-item时,key是不同的 curQueue[3] = addItem; } else if ((total % 3) === 2 && nextQueue.length === 0) { let _pop = curQueue.pop(); this.setData({ _pop: _pop }) } 如果不能理解我讲的,请下载测试代码片段自己测试并验证,有问题可以评论留意,相互学习。(使用在小程序名称为:iTOP-智能名片,需要进去后左滑,进入视频专辑,随便点击一个视频查看即可查看视频滑动效果) 这里的部分核心代码参考此文章(有修改点):https://developers.weixin.qq.com/community/develop/article/doc/0006ecd75fce608033ba9348d51413 官方源码组件地址(没修改过的代码):https://developers.weixin.qq.com/miniprogram/dev/extended/component-plus/video-swiper.html 本文章的代码片段:https://developers.weixin.qq.com/s/1M3qTFmg7ZmA
2020-12-17 - 提高性能的几种写法
任何优秀的大软件里面都是一个优秀的小程序。<br> 点完赞,在查看哦 setData 频繁使用setData会造成js阻塞问题,甚至卡顿,崩溃(崩溃没试过哈);所以我们应该如何用正确的姿势提高性能呢? 尽量把需要setData的内容放到一起setData,不要出现一个函数多个或者同时使用setData; 更新对象内的某个值,不应该整个对象重新更新,只需要更新对应的值即可,例如<br> [代码]this.setData({'userInfo.headImg': '更新的内容'})[代码]; 如果是列表数据,需要改变某个值变成true,也不应该全部数据更新一遍,只需要更新某一个值即可,例如<br> [代码]this.setData({[`list[${index}].show`]: true})[代码]; 页面不需要渲染的数据,尽量不要写在js里面的data里面,你可以定义一个全局参数都可以或者this.timer等生成一个全局变量; setData单次不能超过1M,超过会导致设置不成功,建议分页数据可以使用二维数组设置,例如 [代码]// 1.通过一个二维数组来存储数据 let feedList = [[array]]; // 2.维护一个页面变量值,加载完一次数据page++ let page = 1 // 3.页面每次滚动到底部,通过数据路径更新数据 onReachBottom:()=>{ fetchNewData().then((newVal)=>{ this.setData({ ['feedList[' + (page - 1) + ']']: newVal, }) } } // 4.最终我们的数据是[[array1],[array2]]这样的格式,然后通过wx:for遍历渲染数据 [代码] relativeToViewport 我们会发现很多时候,列表展示都是图文展示,而图片后端又没有提供缩略图,这会导致浏览器一次请求多张图片会非常消耗http请求,并且浏览器也有请求数量限制,例如chrome浏览器就限制一次性最多6个,严重还会影响我们业务接口请求,这时我们使用[代码]IntersectionObserver[代码]就太美妙了 解决思路 先创建对象实例[代码]wx.createIntersectionObserver()[代码]; 用数据列表遍历监听页面渲染的元素; 条件判断,动态设置状态显示图片,如果返回滚动则过滤不需要在setData,减轻js工作任务; js代码 [代码] data: { list: [ // 测试数据自己随便造 {id: 0, url: 'https://devapicard.itop123.com/files/img/20201213/20201213141209123634220.png'}, {id: 1, url: 'https://devapicard.itop123.com/files/img/20201213/20201213141209123634220.png'}, {id: 2, url: 'https://devapicard.itop123.com/files/img/20201213/20201213141209123634220.png'}, ] }, onReady() { let list = this.data.list; list.forEach((item,index)=>{ // 遍历监听元素在页面的位置 wx.createIntersectionObserver().relativeToViewport({bottom: 0}).observe(`.img-${index}`,res=>{ if (res.intersectionRatio > 0 && !list[index].show){ // intersectionRatio值大于0,说明元素出现在视图中了 // console.log(item, 'list', res) this.setData({ [`list[${index}].show`]: true }) } }) }) }, [代码] wxml代码 [代码] <view> <block wx:for="{{list}}" mode="aspectFill" wx:key="index"> <view class="test-img img-{{index}}"> <image class="image" wx:if="{{item.show}}" src="{{item.url}}"></image> </view> </block> </view> [代码] wxss代码 [代码].test-img{ width: 600rpx; height: 400rpx; margin-bottom: 20rpx; overflow: hidden; } .image{ width: 100%; } [代码] onPageScroll 这个监听页面滚动事件,输出顶部滚出页面多少距离,单位是px;这个事件非必要时不要写也不要输出内容,这样会很消耗性能,如果必须要使用到,我们要学会写节流或者防抖事件,减少过快的去setData;下面代码是网上复制,结合自己业务改造下即可 [代码]// 防抖 function debounce(fn, wait) { var timeout = null; return function() { if(timeout !== null) clearTimeout(timeout); timeout = setTimeout(fn, wait); } } // 处理函数 function handle() { console.log(Math.random()); } // 滚动事件 window.addEventListener('scroll', debounce(handle, 1000)); // 节流throttle代码(定时器): var throttle = function(func, delay) { var timer = null; return function() { var context = this; var args = arguments; if (!timer) { timer = setTimeout(function() { func.apply(context, args); timer = null; }, delay); } } } function handle() { console.log(Math.random()); } window.addEventListener('scroll', throttle(handle, 1000)); [代码] 代码分包 代码肯定是越写越多,需求也是越来越多的,小程序单个分包最大只能是2M,这就不能让我们的业务代码都写在主包,这会导致我们无法提交代码,并且也会导致我们打开小程序会很慢,体验很差。 为了解决这个问题,微信提供了小程序总共代码包支持最大16M,还支持我们分包功能,这样我们就可以开发更强大的功能,分包又分为普通分包和独立分包,他们又是什么关系,有何不同? 总的不同是,主包不能调用任何分包的东西,例如js,组件等,但是分包或者独立分包是可以调用或者使用主包的任何东西 分包:分包就是一个可以节省主包代码的一个普通分包,启动分包页面,会把主包下载,普通分包可以使用主包的 js 文件、template、wxss、自定义组件、插件等 独立分包:独立分包不依赖主包即可运行,不需要下载主包,可以很大程度上提升分包页面的启动速度,固并不能使用主包的 js,组件,wxss,插件等 预加载:分包后,如果想打开主包后,跳转不出现加载模块中的等待提示,可以使用预加载,这样就可以做到无缝跳转,增强了用户体验,跳转就像主包跳转主包页面一样顺滑。更多分包讲解请查看微信文档 [代码]{ "pages": [ "pages/index", "pages/logs" ], "subpackages": [ { "root": "moduleA", // 分包 "pages": [ "pages/rabbit", "pages/squirrel" ] }, { "root": "moduleB", // 独立分包 "pages": [ "pages/pear", "pages/pineapple" ], "independent": true // 独立分包的标志 } ], "preloadRule": { // 预加载写法 "pages/index": { "network": "all", "packages": ["moduleA"] // 需要预加载的分包 }, "pages/logs": { "packages": ["moduleB"] // 需要预加载的分包 } } } [代码] 结束 本次写作先到这里,更多丰富好用的内容,请等待下一期~ 都看完了,别忘了给个赞再走~,创作不容易,谢谢哦 本文与掘金号文章同步,欢迎查阅掘金对应的文章
2021-07-09 - 周期性拉取和数据预拉取两种方法使用 wx.setBackgroundFetchToken()
查了社区问题,好像对这两种方法使用,很少人提,或者答案不全,或者没有我想要的结果;然后自己给自己加需求使用了这个东西,得到了一下认识,我就把知道的都说下吧: 先上代码: // 设置周期性或者数据拉取参数 if (wx.canIUse("setBackgroundFetchToken")) { // 判断是否支持该api-2.8.0以上可支持,最好使用基础库判断,我这里简单判断 wx.setBackgroundFetchToken({ token: data.id, }) } 获取数据: // 无论是周期性更新还是数据预拉取都是这个方法,只是参数不同 wx.getBackgroundFetchData({ fetchType: 'pre', // fetchTylpe参数为:pre-数据预拉取,periodic-周期性更新 success(res) { console.log(res.fetchedData) // 缓存数据 console.log(res.timeStamp) // 客户端拿到缓存数据的时间戳 console.log(res.path) // 页面路径 console.log(res.query) // query 参数 console.log(res.scene) // 场景值 } }) 上连个拉取数据成功的截图: 周期性更新,获取到的数据:[图片] 数据预拉取,获取到的数据:[图片] 由结果可以感受到返回结构都是一样的,微信发起数据回调都是在属性fetchedData属性里面,需要进行JSON.parse(); 这里需要注意下: 1、进入小程序后台配置好能请求的GET请求接口,这里是GET请求哦要注意啦。[图片] 2、如果工具提示错误代码:6000101,这个很大可能是因为你配置的接口只支持post或者需要登录认证才能调的接口,报的错误; 3、wx.setBackgroundFetchToken({token: 'xxx'}),这里的token属性key无法修改,当微信调你配置的接口,会在配置的地址后面拼接上toke既(https://baidu.com?token="xxx"); 4、周期性数据,你设置了token也不会马上拉取数据的,测试需要借助开发工具点击数据拉取;数据预拉取,设置token下次刷新就有数据了; 5、周期性更新没12小时更新一次,然后缓存数据,但是不能超过256KB; 数据预拉取:token和code只会存在一个,用于标识用户身份。大小应不超过 [代码]256KB[代码]
2020-07-28 - 一个小程序最多同时开多少个直播间?小程序直播组件直播间的直播时长是否有限制?
同一个小程序最多可以支持50个直播间同时直播,每天的直播上限也是50场。每个直播间不能直播超过12小时。
2020-04-17