- 微信小程序this.setData如何修改对象、数组中的值
在微信小程序的前端开发中,使用this.setData方法修改data中的值,其格式为 this.setData({ '参数名1': 值1, '参数名2': 值2 )} 需要注意的是,如果是简单变量,这里的参数名可以不加引号。 经过测试,可以使用3种方式对data中的对象、数组中的数据进行修改。 假设原数据为: data: { user_info:{ name: 'li', age: 10 }, cars:['nio', 'bmw', 'wolks'] }, 方式一: 使用['字符串'],例如 this.setData({ ['user_info.age']: 20, ['cars[0]']: 'tesla' }) 方式二: 构造变量,重新赋值,例如 var temp = this.data.user_info temp.age = 30 this.setData({ user_info: temp }) var temp = this.data.cars temp[0] = 'volvo' this.setData({ cars: temp }) 方式三: 直接使用字符串,此种方式之前不可以,现在可以了,估计小程序库升级了。 注意和第一种方法的对比,推荐还是使用第一种方法。 this.setData({ 'user_info.age': 40, 'cars[0]': 'ford' }) 完整代码: Page({ /** * 页面的初始数据 */ data: { user_info:{ name: 'li', age: 10 }, cars:['nio', 'bmw', 'wolks'] }, change_data: function(){ console.log('对象-修改前:', this.data.user_info) this.setData({ ['user_info.age']: 20 }) console.log('对象-修改后1:', this.data.user_info) var temp = this.data.user_info temp.age = 30 this.setData({ user_info: temp }) console.log('对象-修改后2:', this.data.user_info) this.setData({ 'user_info.age': 40 }) console.log('对象-修改后3:', this.data.user_info) console.log('数组-修改前:', this.data.cars) this.setData({ ['cars[0]']: 'tesla' }) console.log('数组-修改后1:', this.data.cars) var temp = this.data.cars temp[0] = 'volvo' this.setData({ cars: temp }) console.log('数组-修改后2:', this.data.cars) this.setData({ 'cars[0]': 'ford' }) console.log('数组-修改后3:', this.data.cars) } }) 效果: [图片]
2020-08-26 - Skyline | 快速搞定复杂的分享海报
在小程序中生成海报是一种非常有效的推广方式 用户可以使用小程序的过程中生成小程序海报并分享给他人 通过海报的形式,用户可以直观地了解产品或服务的特点和优势 [图片] 常见绘制海报方式 目前,小程序海报有两种常见的实现方式: · canvas 绘制海报 · 服务端绘制海报 这两种方式各有千秋 canvas 绘制海报使用 canvas 绘制海报主要有以下几个步骤 1、创建 [代码]canvasContext[代码] 2、获取网络图片的本地路径 3、绘制图片、文字等到 [代码]canvas[代码] 4、调用 [代码]wx.canvasToTempFilePath[代码] 导出图片 尽管 canvas 绘制功能强大,但实际使用中,这些操作看似简单,但调试起来却比较麻烦 而且面对一些复杂的排版时,使用 canvas 绘制相较于使用 CSS 绘制来说困难许多 除此之外,canvas 的宽高有最大限制,超出限制则会绘制空白 服务端绘制 小程序也可以通过调用服务端接口,将需要生成海报的数据传递给服务端, 由服务端使用 Canvas API 等第三方库来生成图片。 然而,这种绘制方式需要走网络请求,如果量大会给服务器带来一定的成本压力。 此外,对于复杂排版的实现,使用 Canvas 绘制也有一定的难度。 尽管小程序海报虽然好用,但是当遇到要求比较高的设计稿需要还原海报时,对小程序开发者来说是一个十分让人头疼的问题 考虑到海报在小程序中使用的广泛性,我们把开发者的烦恼交给官方来处理~ 小程序官方推出了 [代码]snapshot[代码] 组件,可以直接将小程序 wxml 导出图片。 snapshot 生成海报 当使用 canvas 或 服务端绘制海报遇到复杂排版时,如 圆角、百分比、自定义字体 等等,实现比较困难。 但是使用 wxml 实现却很简单 👇 下面的例子我们使用 wxml 实现海报 <view class="snapshot-box"> <view class="poster-container"> <view class="poster-header"> <image /> ... </view> <view class="description"> ... </view> <view class="footer"> ... </view> </view> </view> [图片] 接着,我们就可以导出海报啦,使用非常简单: 1、用 [代码]snapshot[代码] 组件包裹海报的 wxml 2、调用 [代码]takeSnapshot[代码] 获取图片数据 3、调用 [代码]fs.writeFileSync[代码] 将海报数据写入本地文件 4、调用 [代码]wx.saveImageToPhotosAlbum[代码] 将海报保存到本地 <snapshot id="view"> <!-- 这里是要海报的 wxml --> </snapshot> <button bindtap="tap">保存海报</button> tap() { this.createSelectorQuery().select("#view") .node().exec(res => { const node = res[0].node // 保存海报 node.takeSnapshot({ type: 'arraybuffer', format: 'png', success: (res) => { const f = `${wx.env.USER_DATA_PATH}/hello.png` const fs = wx.getFileSystemManager(); // 将海报数据写入本地文件 fs.writeFileSync(f, res.data, 'binary') this.setData({ img: f }) // 把海报图片保存到本地 wx.saveImageToPhotosAlbum({ filePath: f }) } }) }) } 最后我们来看看使用 [代码]snapshot[代码] 组件生成海报的效果吧~ [图片] 除了普通尺寸分享海报之外,对于 canvas 无法搞定的超长海报,[代码]snapshot[代码] 后续也会支持超长海报的导出~ [图片] 你的小程序也有海报生成需求吗? 赶紧 mark 下这个 代码片段 来接入使用吧~
2023-09-06 - 云数据库自定义权限问题?
根据微信文档,权限自定义实例: 群聊 ,模拟测试,被拒绝访问 聊天室集合chats: { _id: string, owner: string, // 群主 openid name: string, // 群名 members: string[], // 成员 openid 列表 } 权限定义: { "read": "auth.openid in get('database.chats.$(doc._id)').members", "write": "doc._openid == auth.openid" } 在小程序端, 在云数据库写记录成功如下: _id: "chatRoomId", _openid: "thisMyOpenid". owner: "thisMyOpenid", members: ['openidNo1','openidno2',"thisMyOpenid"], name: "chatRoomName" 在小程序端 读 await database.collection("chats").where({ _id: “chatRoomId”, _openid: '{openid}' }).get() 报错: VM855 WAService.js:3 Uncaught (in promise) Error Error: errCode: -502003 database permission denied | errMsg: SecurityRuleError: 错误的值 (Cannot read property 'members' of undefined) at new u (VM855 WAService.js:2) at Function.success (VM855 WAService.js:2) at Object.success (VM855 WAService.js:2) at y (VM855 WAService.js:2) at v (VM855 WAService.js:2) at VM855 WAService.js:2 at e. (VM853 asdebug.js:1) at VM855 WAService.js:2 at VM855 WAService.js:2 翻来覆去的看文档,不知问题在哪,请求帮助 //////////////////////////////////////新的问题//////////////////////////////////////////////////////////////// @stop eating 这两天我给room增加了几个读取功能,又遇到问题 首先我改了room 的权限为: { "read": "auth.openid in get(`database.chats.${doc._id}`).members || doc.creator == auth.openid", "write": "doc._openid == auth.openid" } 我使用 await db.collection('room').where({_openid: '{openid}',owner: '{openid}'}).get() 获得所有‘{openid}'创建的rooms,这个没问题 然后我使用: await db.collection('room').where({members: _.in(['{openid}'])}).get() 或者 await db.collection('room').where({members: _.in(['one_Openid_In_Members'])}).get() 或者 await db.collection('room').where({}).get() 或者 await db.collection('room').where({_id: _.neq("")}).get() 获得在 room’s members 里的人的所有rooms, 一直出错 Uncaught (in promise) Error Error: errCode: -502003 database permission denied | errMsg: Permission denied 我知道我的查询条件与权限设置 "auth.openid in get(`database.chats.${doc._id}`).members” 不相符 需要在查询中有 _id 参数,但对获得所有room id,显然不行,微信的文档实在是简约,我还没有测试聚合 不知道聚合与这些权限的设置的关系, 我担心可能又是困难重重。 stop eating请帮下忙!
2020-06-10 - 头像昵称填写拿到的头像临时地址怎么保存到服务器?
[图片] 通过wx.uploadFile 上传头像到服务器,上传接口具体要怎么写?临时地址无法访问也无法直接下载,是要做什么处理还是怎么滴?
2023-07-24 - 小程序时区问题
本文系转载,并在文末有标记出处 前言跟异国他乡的朋友们微信聊天的时候,经常面临时差的问题。我每次想要确定对方现在是几点,总是要口算一下,有时忘记具体时差,或者涉及跨天,还得打开浏览器查一下,很不方便。有什么方法可以把朋友们所在城市的时间集中起来随时供自己查看呢?于是想到了微信小程序。找了找市面上的时间小程序,不是功能太杂就是小广告太多,不满意。 为什么不自己动手量身打造一个呢? 行动起来。 首先快速明确需求很简单: 需要展示时间的城市初定:加州、纽约,再加北京做对比需要显示具体的时分秒,和年月日需要实时变化在其他国家也能正确展示时间然后创建项目开撸怎么创建和前期的准备就不在这里展开了,相信不少人都熟悉。如果不熟悉小程序开发的可以参考官网 或者我的另一篇文章如何开发微信小程序 ,上面有对如何开发小程序的简明扼要的的介绍。关键逻辑这个小程序的核心是时间的处理。如何得到其他地区的时刻信息? 这还不简单? 先获取本地时刻,然后加上或者减去另外一个地点与国内(北京时间)的时差(小时),最多再处理一下跨天的情况,不就得到其他地点的时刻了? 我一开始也是这么想的,做完觉得还挺美,准备提交的时候,突然意识到问题:我时差全是基于北京时间计算的,换在其他国家访问,获取的本地时间已经不是北京时间了,时差应该变才对,写死了时差可还行?!发布一个只能在国内使用的鸡肋时间工具,可不是我的风格! 捣鼓一阵,新方案出炉: 想办法获得零时区的时间获取不同地区与零时区的时差(时区)用零时区的时间加减与零时区的时差(时区),得到各地的绝对时间1. 获得零时区的时间零时区,也叫中时区,位于英国格林威治本初子午线上。该时区的地方时,叫做格林威治时间,也叫世界时。 我们不能直接获得格林威治时间,但是我们可以获得本地与格林威治的时间差: const diff = new Date().getTimezoneOffset() // 单位为分钟 然后根据本地时间和时间差获得格林威治时间: const absTime = new Date().getTime() + diff * 60 * 1000; 2. 查询各地时区格林威治本初子午线将地球划分为东西两个半球,格林威治本初子午线为零时区,往西依次为西一区到西十一区,往东依次为东一区到东十一区,西十二区和东十二区重合成为东西十二区,一共划分了24个时区,每个时区相差正好是1个小时。 北京是东八区,纽约是西五区,加州是西八区。 完整时区地图: [图片] 3. 计算各地的绝对时间东时区的时刻比零时区快,西时区的时刻比零时区慢,所以东时区为正,西时区为负,所有时间计算记得转换为毫秒。 let localTime = new Date(absTime + timeZone * 60 * 60 * 1000); 获取任何时区的绝对时间的完整核心代码: /** * timeZone: 东n区为正,西n区为负, 单位为小时 */ const getFullTimeInfo = (timeZone, country, spliter) => { //获取本地时间与格林威治时间的时间差(注意是分钟,记得转换) const diff = new Date().getTimezoneOffset(); //根据本地时间和时间差获得格林威治时间 const absTime = new Date().getTime() + diff * 60 * 1000; //根据格林威治时间和各地时区,得到各地时区的时间 let localTime = new Date(absTime + timeZone * 60 * 60 * 1000) return { time: formatTime(localTime, spliter) }; } 发布很快,第一版就完成了。 [图片] 刚开始这个样子略丑,有点裸奔的赶脚。不过第一版最主要是核心功能,简陋的界面只是暂时的。 给当地的朋友检验确定时间展示正确后,提交代码、提交审核,2天后收到审核通过的通知(吐槽腾讯的审核效率😓),然后在小程序管理平台点击发布,哦了。 扫描二维码,打开小程序,然后收藏。以后要看时间了,微信主界面向下一拉,打开我的时间工具,一眼就看到想要知道的时间信息,确实比之前便捷多了。功能虽然简单,界面虽然简陋,但是妥妥滴满足我的需求。 迭代用了一阵子,觉得样式啥的还是得丰富丰富,于是花了一些时间做了一次改版,实时时间以时钟效果展示,并且修改了布局,顺便重构了一下代码,便于新增地区。 [图片] 嗯,效果似乎还行~ 改BUG前几天跟澳洲的朋友聊天,聊着聊着居然发现了我的程序的一个潜在BUG。 那天是4月4日的早晨(北京时间),我跟朋友吐槽我的一个疑惑:查询悉尼时区为东十区(即与北京相差2小时),但是为啥查询悉尼时间却与北京相差3小时(所以我当时程序中是把悉尼作为东十一区来计算的)。朋友说:是的没错,我们这里现在在使用夏令时,等夏令时结束就恢复2个小时时差了。然后一查,今年澳洲夏令时将在4月5号凌晨3点结束。。。 也就是说,距离这个BUG发作还有不到一天的时间。。。 马上打开电脑,改BUG。。。 根据资料,获得美国和澳大利亚的夏令时规则: 美国每年的3月第二个星期日02:00:00,时钟向前调整1小时,变为03:00:00,开始夏令时。 每年的11月第一个星期日02:00:00,时钟向后调整1小时,变为01:00:00,结束夏令时。 澳大利亚每年的10月第一个星期日02:00:00,时钟向前调整1小时,变为03:00:00,开始夏令时。 每年的4月第一个星期日03:00:00,时钟向后调整1小时,变为02:00:00,结束夏令时。 关于夏令时,也挺有意思,有空我会另开一个篇幅来专门讲述。将夏令时的判断逻辑加上: /** * timeZone: 东n区为正,西n区为负, 单位为小时 */ const getFullTimeInfo = (timeZone, country, spliter) => { //获取本地时间与格林威治时间的时间差(注意是分钟,记得转换) const diff = new Date().getTimezoneOffset(); //根据本地时间和时间差获得格林威治时间 const absTime = new Date().getTime() + diff * 60 * 1000; //根据格林威治时间和各地时区,得到各地时区的时间 let localTime = new Date(absTime + timeZone * 60 * 60 * 1000) + // 考虑夏令时 + // judgeDST是我封装好的一个判断夏令时的方法 + const isDST = judgeDST(localTime, country); + if (isDST) { + localTime = new Date(absTime + (timeZone + 1) * 60 * 60 * 1000) + } return { time: formatTime(localTime, spliter).split(':').slice(0,2).join(':'), isDST }; } 有了现在的版本: [图片] 以后对这个小工具我还会不断优化,会越来越灵活,比如支持地区选择,这样每个人都可以定制自己的时差表了。可以期待一下哦~ 最后附上小程序二维码,扫一扫即可体验。 [图片] -- 还是毛爷爷说得好:自己动手丰衣足食。 Happy coding :) 本文作者:ChampYin转载请注明出处:http://champyin.com/2020/04/08/开发一个时间小程序/
2020-06-01 - 云存储到对象存储COS的迁移
云开发计费调整后,对存储和CDN用量较大的业务成本影响较大。把文件从云存储迁移到对象存储(下文简称 COS ),是一个成本优化的选择。 我自己的小程序比较下来,每月的费用大约是不迁的三分之一(刚好也赶上双11的活动攒了一波优惠资源);如果不考虑活动,正常买资源包,大约也能降低一半。 但相比从零开始就是「云函数 + 云数据库 + COS」的架构,就急需一个高效稳定的迁移方案,迁移云存储中的文件,并同时更新数据库记录。最好还无需停服。 这里就不赘述那些尝试过的失败方案,仅记录并分享最后跑通的流程,供有类似需求的开发者朋友参考。 一、开通并设置COS、CDN 在腾讯云创建COS的存储桶(最好和云存储同地域,之后迁移既快又经济),「权限管理」设置为“私有读写”,避免外网的直接下行访问;注册或找个域名,设置为 COS 的「自定义CDN加速域名」,开启「回源鉴权」;进入「内容分发网络」的「域名管理」,在「管理」的「访问控制」,开启「防盗链配置」——类型选「白名单」,填入小程序域名“servicewechat.com”。这里需要开启「允许空 referer 访问」,如不开启,手机端将无法访问 video 组件的视频文件(这个问题至今尚未修复)。二、准备小程序的更新版,提交审核(增删改查指向COS新路径) 在腾讯云控制台「访问管理」中创建一个子用户角色,获取 secretId 和 secretKey;写一个云函数,通过 secretId 和 secretKey 生成临时密钥;客户端上传文件时,先触发这个云函数获取COS的临时密钥,用于客户端 wx.uploadFile 文件上传;上传完成后,回调函数里获取 COS 文件路径,写入云数据库;以上是“增”,“删改查”同理,不赘述(访问 COS 的云函数,需要通过 npm 给云函数装 COS 的 Node.js SDK)。详细实践可参考腾讯云文档:小程序直传实践。 新版本准备好了便提交小程序审核。 三、写迁移云函数 因云函数默认内存256M、超时时间3s,最大也只可设置为 1024M、60s,如不够用,可将迁移过程拆为任务发起函数和执行函数;发起函数获取需要迁移的文件数据(如数据量大,可根据数据结构再拆分云函数读取),异步调用执行函数,不等执行结果;每个执行函数只执行一个文件的迁移、及更新数据记录的任务。这样执行时云函数都不会超过内存和时间限制;执行函数里,先 cos.downloadFile 云存储的文件到云函数的缓存(注意路径是“/tmp/文件名”,不是“__dirname/文件名”),再从缓存 cos.uploadFile 到 COS。四、发布小程序、执行迁移 小程序审核通过、迁移云函数都准备好后: 小程序新版发布上线;通过IDE编译,触发迁移云函数里的发起函数。迁移全程同地域内网执行(不要用本地调试。公网执行慢很多,容易超时,且会产生公网流量费);因为执行函数并发量大,容易受到云函数并发数的500/分钟的限制,500以上的都会执行失败(500是入门版到团队进阶版的每分钟并发数,个人版100,更贵的版本更高)。因此执行函数里只能执行一个文件迁移就立即更新相应记录,不能汇总了再更新;如数据量很大、发起函数拆分后读取仍超时,可在数据库记录任务发起情况,多触发几次,总会迁移完。在这个尝试迁移的过程中,有幸得到腾讯云工单同学、客户经理、云开发产品经理的支持和点拨,多次在挠头时刻解惑。感谢。 才疏学浅,如有谬误,请多多指正~
2022-12-20 - 云存储,400G的内容转移到COS对象存储,尝试的方法
因为云存储内容价格暴涨,公司要求将内容全部转移到cos对象存储中。研究尝试了好几个方法都不行,最后老老实实的写代码下载转存。有好办法的请分享,感谢! 方法一:使用官方推出的工具:CloudBase CLI批量下载,开开心心的按照教程做了,结果因为文件太多,还没开始就堆栈溢出了,放弃。 [图片] 方法二:使用云存储http下载接口下载,使用COS上传接口上传,速度太慢且容易出现未知问题,放弃。 方法三:导出已存储内容的数据库记录,通过直链将文件下载到本地(多线程批量校验下载),然后在使用COSBrowser 客户端,批量上传到COS,耗时1.5天,已完成。 [图片]
2022-09-26 - 共享云环境时代来了,解决fileID带来不兼容问题。
云开发收费了,不管你怎么选择,只要你还继续使用云开发,共享云环境的课题就不可避免。 我们知道,共享云环境下,fileID是无法使用的,怎么兼容,一个最简的方法如下: <wxs module="wxs"> module.exports = { getUrl: function (link) { if (link) { } else return '' if (link.substring(0, 5) == 'cloud') { } else return link var arr = link.split('/') arr[0] = 'https:' arr[2] = arr[2].split('.')[1] + '.tcb.qcloud.la' return arr.join('/') } } </wxs> <image src="{{wxs.getUrl(link)}}"></image> 可见:只要将原项目所有的fileID换成wxs.getUrl(link) 其他代码可以一分不动,也不需要用到wx.cloud.getTempFileURL 可以将wxs.getUrl放在lib.wxs里,任何wxml引用即可。
2022-10-28 - Half Screen Dialog半屏弹窗内部可以自定义吗
本文主要解决了以下两个问题 1、weui如何引入 2、半屏弹窗如何使用 3、半屏弹窗是否支持内部自定义 如果对上面三个问题感兴趣可以继续阅读 Half Screen Dialog半屏弹窗,辅助完成当前页面任务时;提醒用户并引导用户的下一步操作;用户主动发起的任务时。 https://developers.weixin.qq.com/miniprogram/dev/extended/weui/half-screen-dialog.html 1 [图片] 2 [图片] 3[图片] [图片] 3 如何引入Weui,有两种方式,本文分别说一下, 1、传统方式 首先node npm xx,然后把里面的dist目录移出来。 官方文档 https://developers.weixin.qq.com/miniprogram/dev/extended/weui/quickstart.html 2、扩展方式,当然扩展方式有优势,但是有时候不是那么容易调试出来。 参考社区帖子 https://developers.weixin.qq.com/community/develop/article/doc/000224381788e8e5bb89426f55e413 更新最新的 nightly 版开发者工具在app.json里新增“useExtendedLib”: {“weui”: true}在使用的页面json文件应用组件,比如在index.json里{“navigationStyle”:“custom”,“usingComponents”: {“mp-navigation-bar”:"/weui-miniprogram/navigation-bar/navigation-bar"}}wxml文件使用组件,比如在index.wxml里<mp-navigation-bar title=“首页”></mp-navigation-bar>验证有效。 4 [图片] 5 6 我把评论区大佬的代码片段提上来了,非常感谢。 https://developers.weixin.qq.com/s/yWl6plmy7ghb 相关代码我都放评论区域了,需要的话,可用自取。
2020-05-15 - 小程序自定义tabbar,以及激活状态闪烁的解决方案
小程序官方代码如下(自定义tabbar组件) [代码]Component({ data: { selected: 0, //代表当前激活状态 color: "#7A7E83", selectedColor: "#3cc51f", list: [{ pagePath: "/index/index", //app.json 中定义是index/index,在这里需要在前面加上/:/index/index iconPath: "/image/icon_component.png", selectedIconPath: "/image/icon_component_HL.png", text: "组件" }, { pagePath: "/index/index2", iconPath: "/image/icon_API.png", selectedIconPath: "/image/icon_API_HL.png", text: "接口" }] }, attached() { }, methods: { switchTab(e) { const data = e.currentTarget.dataset const url = data.path wx.switchTab({url}) this.setData({ selected: data.index //代表切换激活状态 }) } } }) [代码] 小程序tabbar,在路由跳转时,会恢复初始激活状态,所以必须在跳转的页面里加上这样一段代码 [代码]//官方写法,会带来一个bug,有时pageLifetimes里的show不会执行 Component({ pageLifetimes: { show() { //代表父组件页面显示时,子组件执行的方法 if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 0 //将tabbar的值重新设为当前页面需要激活的值 }) } } } }) [代码] 可以使用以下写法修复,将Component改为Page,方法写在onShow里即可 [代码]Page({ onShow() { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 0 }) } }, }) [代码] 小程序自定义tabbar完成,不过在实际项目中,会出现以下问题,小程序会激活其他tabbar再激活当前tabbar,可以这样解决,自定义tabbar.js修改如下: [代码]Component({ data: { selected: "", //只需要将它的初始激活状态从指定的值设为空,就行 color: "#7A7E83", selectedColor: "#3cc51f", list: [{ pagePath: "/index/index", iconPath: "/image/icon_component.png", selectedIconPath: "/image/icon_component_HL.png", text: "组件" }, { pagePath: "/index/index2", iconPath: "/image/icon_API.png", selectedIconPath: "/image/icon_API_HL.png", text: "接口" }] }, attached() { }, methods: { switchTab(e) { const data = e.currentTarget.dataset const url = data.path wx.switchTab({url}) this.setData({ selected: data.index }) } } }) [代码] 完美解决,因为小程序路由跳转,tabbar会重新加载一次,就会有初始值,进入一个新的页面时,会先显示初始值,再显示设置的值,就会出现闪烁效果。 PS:可以在tabbar的switchTab方法中使用全局变量app.globalData存储要跳转的selected值,在自定义tabbar的attached生命周期中,将selected设置为app.globalData中存储的新路由值,tabbar的切换效果会更好。
2022-10-20 - 全网最全小程序自定义tabbar实现方案
业务需求,底部导航栏(tabbar)支持自定义,目前有个局限性,必须要在app.json里面声明list数组,而且数量是五个,导致扩展受限制。目前还没有解决办法,基本可以满足五个和小于五个自定义的已存在的tabbar的动态配置。 感谢网友的热心分享,以下链接地址都非常有参考价值:不过在当前时间点2020年6月5号,和对应的小程序版本号来说或多或少会遇到一些问题。 2022-08-30 补充: 首先很抱歉,就是图片看不到了.确实影响阅读体验. 然后这个方案是不成熟的, 大家可以巧用: wx.setTabBarItem 这个api,来做一些文章. 其实可以用wx.setTabBarItem https://developers.weixin.qq.com/miniprogram/dev/api/ui/navigation-bar/wx.setNavigationBarTitle.html 参考地址:见文章结尾 自定义 tabBar 官方api地址:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html?search-key=%E8%87%AA%E5%AE%9A%E4%B9%89tabbar 效果图先上: [图片] 小程序自定义tabbar实现.gif 下面开始进入正文: 第一步、先下载官方的demo,然后进行合并。说明:这里存放的目录地址要是项目下和pages同目录,不然无法识别自定义的tabbar组件[图片] image.png 说明2,这个用的是全局设置的,需要加一下,不然不能开启自定义组件模式 "usingComponents": {}, "window": { 第二步、在 app.json 中的 tabBar 项指定 custom 字段,设置为true,同时其余 tabBar 相关配置也补充完整。说明:如果遇到报错,说什么组件不存在,可以把 custom 字段去掉,本项目没有去掉能正常使用。[图片] image.png 第三步、修改custom-tab-bar/index.js的文件说明,由于这里我们是后端动态返回的,这里我不展开说具体的业务,这里需要注意的是list中的pagePath一定要写绝对路径/pages开头第四步、把官方给的使用方法放到tabbar跳转页的onShow方法里,selected根据list下标位置进行设置selected: 这里的参数是对应的底部tabbar的顺序的,含义是进入当前界面,并选中这个当前的tabbar if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 4 }) } 第五步,关于点击后会闪一下这个问题的说明,目前官方也没有解决的方案,所以,除非必要,建议还是用自带的tabbar写业务。[图片] image.png 最后补充一个兼容跳到tabbar的语法糖: wx.navigateTo({ url: '/pages/cart_new/index/index', success: function(res) {}, fail: function(res) { wx.switchTab({ url: '/pages/cart_new/index/index', //注意switchTab只能跳转到带有tab的页面,不能跳转到不带tab的页面 }) }, complete: function(res) {}, }) 参考地址: 微信小程序开发---自定义tabBar:https://segmentfault.com/a/1190000016283268 微信小程序自定义tabbar:https://www.jianshu.com/p/8b918e21cc6b 小程序自定义tabbar报Component is not found in path "custom-tab-bar/index":https://blog.csdn.net/qq_34672907/article/details/93624433 微信小程序自定义导航栏天大的坑,报错提示:component is not found in path "custom-tab-bar/index"...https://blog.csdn.net/dqzd12345/article/details/102756681 鉴于文中图片丢失:可以移步到我的博客看文中图片 https://www.jianshu.com/p/c48281e61907?u_atoken=b039edc7-97e0-4fa9-9d2d-4aca9a1faa87&u_asession=01VEYqQobFRt91aDKSjf6RMv2PFMk-NGAnJp1a80FUHt5puOXqVMQ49qq2C1XR8xKKX0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K_wjOK6EbT2ki0dkwQctnAQnHmbkqVcEgdObpAroqY1_GBkFo3NEHBv0PZUm6pbxQU&u_asig=05ESJ0rAXmqHXPIepLzgwTZn_I1UfOjo4mnyB5w-1YuP98oKPx90Z-OI_FpFckab0IKcUl39blHNAEIyPVHalH7evI9N43IRLtrs4TIbEtbub6fJW-7KGDLiz20hzMsz99AoqUieIp1TcUCwzplBT-dwzjA8FeyDmEzHEoYBRMWeH9JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzYGzTYSVKNX8WdtkFZgDm7lSpGaDCR7AutzhN5tKbTbm6xbSxAaWh9ph0bRUFW-6vO3h9VXwMyh6PgyDIVSG1W-u2m4aSV3j7RjNp-oJ3rx3fX5y-uYeLDQishV-vt1GW8_QLnW4q9Rmwoz8SvMcA9UV9IzhK00je8y5MzvIwdeImWspDxyAEEo4kbsryBKb9Q&u_aref=uxwZVbN3vBalaKU8R2iVPkmS7C4%3D
2022-08-30 - 小程序订阅消息data内容如何换行?
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html 小程序订阅消息,data数据内容,业务需求想完成指定字段内容换行,使用\n、\r、\r\n均无效,请问有无方法解决?
2022-05-31 - 云开发·多次订阅一次性订阅消息后定时发送
小程序一次性订阅消息,订阅1次可以发送1条消息,订阅10次可以发送10条消息。 1. 前情提要,完成订阅到发送的过程 订阅部分参考 实战分享: 小程序云开发玩转订阅消息 就可以完成从小程序订阅、存入云开发数据库、利用定时触发器定期发送消息了。 完成上面的步骤,你应该已经在云端做到了: 定时任务 查询所有订阅消息 循环发送消息 发送后根据[代码]_id[代码]标记状态为已发送 但是上文的订阅消息,适用于只订阅一次的情况,查看github的源码,甚至为了避免重复,同一个用户不能订阅多次。 我们要做的逻辑是,同一个一次性订阅消息,用户可以订阅多次,订阅几次就发送几次。 2. 改造查询,支持每个用户只发送一条 保存处代码不用修改,用户多次订阅就会插入多条记录。查询代码需要做修改,目前的查询代码是这样的: [代码] const messages = await db .collection('messages') .where({ done: false, }) .get(); [代码] 查询到了所有未发送的消息,此时一个用户订阅2次,都会查出来,并收到2条订阅消息。 我们使用 [代码]aggregate[代码] 把这里改为类似MySQL中的 [代码]distinct[代码] 查询: [代码]db.collection('messages') .aggregate() .match({ done: false, }) .group({ "_id": '$touser', "idList": $.addToSet("$_id") }) .end() [代码] 注意这里的 [代码]addToSet[代码] 是把前面查询的结果,根据[代码]touser[代码](也就是用户的[代码]openid[代码])重新聚合,把每条消息的 [代码]_id[代码] 放到一个列表中,看起来如下: [代码][ { "_id": "oiRsI0RKU8IG2Y9Z_Y6Y5aC9JGt0",// openid "idList": [ "112557505f9001d1001f90eb23d5894b", // 数据库_id "2c9645925f8f097d001dd5170f0b7727" // 数据库_id ] }, { "_id": "oiRsI0d8Zp8e1edtDlPeuNUZWB68", "idList": [ "2c9645925f900210001eb0814df399fc", "d9ea4cfd5f90020c001b5ab04fc0ed01", "8f29e52a5f8f0972001b9015226aaad9" ] } ] [代码] 这样我们发送时,从 [代码]idList[代码] 中取一个[代码]_id[代码]标记为已发送,就能实现**每次只消耗1次“资格”**了。 3. 分页与循环查询 官方文档指出云端函数Collection.limit 最多 [代码]1000[代码] 条,但是实际上有人测试过Aggregate 聚合操作可以 最多查询 10000 条!。具体限制各位自己测试,如果你的订阅非常多的话,就需要加入循环也分页了。 先查询记录总数,再分页查询,然后再聚合。 注意上面的顺序,因为是先分页再聚合,所以最终出来的结果可能会少于每页条数,不过我们都是汇总再发送,对我们影响不大了。 4. 附加说明 因为我的需求比较简单,前面的查询代码没有区分模板消息种类,有需要的同学可以增加查询条件。 如果需要在集合里展示更多字段,[代码]addToSet[代码]可以这样写: [代码]$.addToSet({'id':"$_id","templateId":"$templateId"}); [代码] 代码已经开源,欢迎围观:https://github.com/PlayerYK/coupon_open 。 。 。 。 最后,觉得有帮助记得点个赞 ⬇️点赞处⬇️
2022-03-28 - 云开发原子操作实现秒杀功能
直接上代码: DB.collection('product').where({ _id: productId, stock: _.gt(0)//库存大于0 }).update({ data: { stock: _.inc(-1),//库存减 1,原子操作inc。 luckers: _.addToSet(openid)//记录获奖者的openid } }).then(res => { //注意如何判断结果 if (res.stats.updated == 1) { console.log('获得奖品') } if (res.stats.updated == 0) { console.log('啥也没抢到') } })
2022-11-09 - 云开发自身如何对外提供回调URL
在小程序云开发开发过程中我们会遇到这样的场景,比如支付,我们需要一个回调地址;比如在使用有赞商城的过程中,利用有赞提供的的api统计商城的一些数据,这时候会需要一个回调地址用来接收有赞商城数据的推送;再比如,小程序中链接硬件,硬件需要定时推送状态到小程序,这时候还需要一个推送地址。最初的解决的方案是,建立一个第三方服务器(或者利用腾讯云云函数功能)来作为中转,提供可调用的URL,然后在URL对应的函数方法中调用小程序云函数。这样虽然可以实现需求,但是会造成维护的成本增加,以及一些不必要的支出。那么有没有通过云函数自身对外提供可调用的URL呢?有的,实现方案如下: 1,打开腾讯云,登录方式选择微信公众号(小程序管理员扫码),选中小程序授权登录 [图片] [图片] 2,搜索并打开云开发CloudBase,点击对应的小程序环境 [图片] [图片] 3,选择云函数,点击http访问 [图片] 4,新建对外调用URL,填写出发路径 ,及对应的云函数实例 [图片] [图片] [图片] 5,点击刚才创建的Http访问服务 [图片] [图片] 浏览器地址栏地址即对外调用链接
2020-11-15