- 小程序用户头像昵称获取(含部分常见问题)
小程序用户头像昵称获取 引言 前段时间,小程序头像昵称获取的接口进行了调整,原公告《小程序用户头像昵称获取规则调整公告》。 简单来说,现在获取用户的微信头像和昵称要用户自己填写了。 下面和大家分享一下「头像昵称填写能力」的实操过程。 「头像昵称填写功能」实操 一、头像部分 WXML 首先,在wxml页面上添加一个[代码]button[代码]组件,设置[代码]open-type[代码]属性为[代码]chooseAvatar[代码],再添加一个触发事件[代码]bindchooseavatar[代码],代码如下: [代码] <button open-type="chooseAvatar" bindchooseavatar="bindchooseavatar"> <image src="{{avatarUrl}}"></image> </button> [代码] 我这里在[代码]button[代码]里面添加了[代码]image[代码]组件是为了实现点击头像(图片)就触发头像选择。 JS 在js部分,写好[代码]bindchooseavatar[代码]事件回调。 [代码] bindchooseavatar(e) { console.log("avatarUrl",e.detail.avatarUrl) } [代码] 当我们触发组件,选择好头像后,我们可以从事件回调中得到头像链接[代码]avatarUrl[代码]。 我这里获取到的链接是: [代码]http://tmp/bnMmEbfpqclVa77acadd216b18c692b3a2aa1d505353.jpeg[代码]。 [图片] 需要注意的是 这里获取到的是本地临时链接,只能在本地中读取与使用,随时会失效。 我们还需要将这个临时路径保存到服务器中,从而换取一个永久链接。 我们可以用API[代码]wx.uploadFile[代码]将图片上传到自己的服务器,改写后的[代码]bindchooseavatar[代码]事件回调代码如下: [代码] bindchooseavatar(e) { const avatarUrl = e.detail.avatarUrl console.log("avatarUrl", avatarUrl) wx.uploadFile({ url: 'https://www.hlxuan.top/upload', // 仅为示例,非真实的接口地址 filePath: avatarUrl, name: 'file', // 文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容 formData: { 'user': 'test' }, // HTTP 请求中其他额外的 form data success (res){ const data = JSON.parse(res.data) // do something } }) } [代码] 如果你用的是小程序云开发,[代码]bindchooseavatar[代码]事件回调代码示例如下: [代码] bindchooseavatar(e) { const avatarUrl = e.detail.avatarUrl console.log("avatarUrl", avatarUrl) wx.cloud.uploadFile({ cloudPath: 'example.png', // 上传至云端的路径 filePath: avatarUrl, // 小程序临时文件路径 success: res => { // 返回文件 ID console.log(res.fileID) // do something }, fail: console.error }) } [代码] 二、昵称部分 WXML 组件自带安全检测功能,根据官方的文档说明,检测是在[代码]onBlur[代码]事件触发时异步进行的,也就是说,如果使用[代码]bindinput[代码]、[代码]bindblur[代码]、[代码]bindfocus[代码]、[代码]bindconfirm[代码]这些的回调去获取用户输入的昵称,就可能会获取到未通过安全检测的内容。 在基础库2.29.1中,新加入了回调 [代码]bindnicknamereview[代码],当安全检测完成后会进行回调 [代码]event.detail = { pass, timeout }[代码] 。 你可以用这个判断用户当前输入的昵称是否通过了安全检测,和检测是否超时。 文章内容更新于2022年12月29日 建议使用表单[代码]form[代码]来收集用户输入的昵称。 [图片] [代码] <form bindsubmit="formsubmit"> <input type="nickname" placeholder="请输入昵称" name="nickname" /> <button form-type="submit" type="primary">提交</button> </form> [代码] 我们需要给[代码]input[代码]设置一个[代码]name[代码]属性,这样才能在回调中获取到用户输入的昵称。 JS [代码] formsubmit(e){ const nickName = e.detail.value.nickname console.log("nickName", nickName) // do something }, [代码] 获取到用户输入的昵称后,你可以将其保存到数据库里面。 Q&A 下面是我在微信开放社区经常看到的一些问题,稍微整理了一下,希望能帮助大家。 1. 为什么「wx.getUserProfile」返回的是“灰色头像”和“微信用户”? 「wx.getUserProfile」接口有调整,参考公告《小程序用户头像昵称获取规则调整公告》。 2. 为什么有部分小程序仍能使用以前的接口获取头像? 公告中:“生效期前发布的小程序版本不受影响”。你看到接口能正常返回头像和昵称的小程序,基本上都是在生效期前发布的小程序,你可以去「更多资料」页面看看它的更新时间。 [图片] 针对下面这个问题,我这边测试了一下,生效期后发布的小程序,基础库低于2.27.1版本,是可以正常返回微信头像和昵称的。这个目前应该只能在 PC/macOS 平台上使用,手机上大部分使用不了的,因为 PC/macOS 平台目前的基础库版本低于2.27.1,所以可以正常返回微信头像和昵称。 [图片] 文章内容更新于2022年12月29日 3. 我调整了基础库版本后,工具上可以返回头像和昵称,真机就不行了? 用户客户端的基础库版本开发者是无法控制的,这个基础库版本会随着微信客户端的更新而更新,可以看下「基础库版本分布」。 在开发者工具上设置的基础库版本,仅用于开发者工具内的调试,所以不能调整移动设备的基础库版本。 [图片] 旁边的「推送」按钮只能将基础库版本推送到你登录开发者工具的微信号上(登录这个微信号的手机上),这并不能改变用户的基础库版本。 4. 我在小程序后台设置了基础库2.27.0或以下版本,为什么还是不能获取头像和昵称? 小程序后台里面设置的是「基础库最低版本设置」,当用户的基础库版本低于你设置的最低版本要求时,将无法正常使用小程序,并提示更新微信版本。 [图片] 5. 「头像昵称填写」有安全检测吗? 有的,组件在基础库2.24.4版本起,已经接入了内容安全服务端口。如果昵称或头像有异常时,页面会显示消息提示框,输入的昵称会被清空,头像也不会返回临时路径。请不要完全依赖内容安全服务。 6. 选择的头像会自动裁剪为1:1吗? 对于来自基础库2.28.1及以上版本,组件自带压缩和裁剪功能;对于来自基础库2.28.1以下版本,你可以做兼容处理。 经验分享:我在自己的小程序里面进行了判断,当基础库2.28.1以下版本时,调用「wx.cropImage」接口对用户选择的头像进行裁剪。 7. 为什么获取到的头像链接在浏览器上打不开? 通过「头像填写能力」获取到的链接为本地临时链接,只能在本地中读取与使用,随时会失效。 [图片]
2023-01-08 - 那些微信小程序开发踩过的坑
小程序页面栈最多十层 问题:小程序内超过十层路由,你会发现wx.navigateTo跳转不到下一个页面。这是因为使用wx.navigateTo跳转会把当前页面保存到页面栈中,而小程序页面栈最多十层。 解决:超过十层使用redirectTo(重定向)操作 或者参考https://developers.weixin.qq.com/community/develop/article/doc/000a08e12185187bd5cebf3f651013 IOS使用New Date()报错IOS 的 Date 构造函数 不支持2018-04-26这种格式的日期,必须转换为2018/04/26这种格式,可以使用 replace(/-/g, '/')处理image组件使用webp图片时,IOS需要设置webp属性.Android手机在onShow内调用 wx.showModal ,如果不关闭弹窗(直接点击右上角退出小程序),弹窗不会销毁,再次进入页面触发onShow时会出现两次弹窗,IOS正常小程序中使用 web-view打开pdf , IOS 可以正常打开,Android 打开为空白 解决:使用wx.downloadFile和wx.openDocument 在手机相册中选择完图片后直接跳转会出现闪回的现象 原因:在选择完图片后,会重新执行一遍page的onShow生命周期 解决:在选择完图片后,做一个sleep延时1秒,再进行跳转 textarea 层级问题 问题:textarea的placeholder会显示在弹窗的层级之上 解决:使用wx:if 判断当没有值的时候用view代替textarea 最好封装为组件 或者 弹出层使用cover-view组件,而不是view,覆盖住所有原生组件。 小程序的 web-view 中页面跳转后,点击 Android 手机上的物理返回按钮会返回前一个页面。而点击左上角的返回按钮,会直接关闭整个 web-view。有关 web-view 中有背景音乐,后台后无法关闭的问题 https://developers.weixin.qq.com/community/develop/doc/c75139c842a40c67cade23d3f66e7992 var hiddenProperty = 'hidden' in document ? 'hidden' : 'webkitHidden' in document ? 'webkitHidden' : 'mozHidden' in document ? 'mozHidden' : null; if (hiddenProperty) { var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange'); var onVisibilityChange = function() { if (document[hiddenProperty]) { !MpMovie.video.paused && MpMovie.video.pause(); } }; document.addEventListener(visibilityChangeEvent, onVisibilityChange);
2022-11-07 - 小程序全局状态管理工具
项目说明 原生微信小程序全局状态管理工具,轻量,便捷,高性能,响应式。 npm链接 :https://www.npmjs.com/package/@savage181855/mini-store 安装 [代码]npm i @savage181855/mini-store -S [代码] 快速入门 在[代码]app.js[代码]文件调用全局 api,这一步是必须的!!! [代码]import { proxyPage, proxyComponent } from "@savage181855/mini-store"; // 代理页面,让页面可以使用状态管理工具 proxyPage(); // 代理页面,让组件可以使用状态管理工具 proxyComponent(); // 这样子就结束了,很简单 [代码] 定义[代码]store.js[代码]文件,模块化管理 [代码]import { defineStore } from "@savage181855/mini-store"; const useStore = defineStore({ state: { count: 0, }, actions: { increment() { this.count++; }, }, }); export default useStore; [代码] [代码]indexA.js[代码]页面 [代码]// 导入定义的 useStore import useStore from "../../store/store"; Page({ // 注意:这里使用 useStore 即可,可以在this.data.store 访问 store useStoreRef: useStore, // 表示需要使用的全局状态,会自动挂载在到当前data里面,自带响应式 mapState: ["count"], // 表示想要映射的全局actions,可以直接在当前页面调用 ,例如:this.increment() mapActions: ["increment"], watch: { count(oldValue, value) { // 可以访问当前页面的实例 this console.debug(this); console.debug(oldValue, value, "count change"); }, }, onIncrement1() { // 不推荐 this.data.store.count++; }, onIncrement2() { this.data.store.patch({ count: this.data.store.count + 1, }); }, onIncrement3() { this.data.store.patch((store) => { store.count++; }); }, onIncrement4() { this.data.store.increment(); }, }); [代码] [代码]indexA.wxml[代码] [代码]<view> <view>indexA</view> <view>{{count}}</view> <button type="primary" bindtap="increment">+1</button> <button type="primary" bindtap="onIncrement1">+1</button> <button type="primary" bindtap="onIncrement2">+1</button> <button type="primary" bindtap="onIncrement3">+1</button> <button type="primary" bindtap="onIncrement4">+1</button> </view> [代码] [代码]indexB.js[代码]页面 [代码]// 导入定义的 useStore import useStore from "../xxxx/store.js"; Page({ // 注意:这里使用 useStore 即可,可以在 this.data.store 访问 store useStoreRef: useStore, // 表示需要使用的全局状态,会自动挂载在到当前data里面,自带响应式 mapState: ["count"], }); [代码] [代码]indexB.wxml[代码] [代码]<view> <view>indexB</view> <view>{{count}}</view> </view> [代码] 全局混入 [代码]app.js[代码]文件 [代码]import { proxyPage, proxyComponent } from "@savage181855/mini-store"; // 这里的配置可以跟页面的配置一样,但是有一些规则 // 'onShow', 'onReady', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', // 'onPageScroll', 'onResize', 'onTabItemTap'等方法,全局的和页面会合并,其余的方法,页面会覆盖全局的。 proxyPage({ onLoad() { console.debug("global onLoad"); }, onReady() { console.debug("global onReady"); }, onShow() { console.debug("global onShow"); }, onShareAppMessage() { return { title: "我是标题-- 全局", }; }, }); // 这里的配置可以跟组件的配置一样,但是有一些规则 // 'created','ready','moved','error','lifetimes.created','lifetimes.ready', // 'lifetimes.moved','lifetimes.error','pageLifetimes.show','pageLifetimes.hide', // 'pageLifetimes.resize'等方法,全局的和组件会合并,其余的方法,组件会覆盖全局的。 proxyComponent({ lifetimes: { created() { console.debug("global lifetimes.created"); }, }, }); [代码] 代码片段 https://developers.weixin.qq.com/s/ZO0SX2mr7xDj
2022-10-15 - 小程序新手引导实现思路整理
从个人开发和使用角度来说,新手引导属于一个比较鸡肋的功能。 [图片] [图片] 反正就是有几个提示,就弹几个框。这里采用的方式是,用三倍图片,然后用2倍的尺寸,然后加上一个黑科技属性,可以做到弹框图片高清不模糊的效果。 话不多说直接上代码:使用点击 +1,的逻辑动态显示对应的图片 <Mask v-if="showGuide"> <view class="maskGuide"> <view v-if="guideNumber == 1" @tap="clickToNext"> <image src="XXX.png" class="tl-img-1"/> </view> <view v-if="guideNumber == 2" @tap="clickToNext"> <image src="XXX.png" class="tl-img-2"/> </view> <view v-if="guideNumber == 3" @tap="clickToNext"> <image src="XXX.png" class="tl-img-3"/> </view> <view v-if="guideNumber == 4" @tap="clickToNext"> <image src="XXX.png" class="tl-img-4"/> </view> <view v-if="guideNumber == 5" @tap="clickToNext"> <image v-if="gender==1" src="XXX.png" class="tl-img-5"/> <image v-else src="XXX.png" class="tl-img-5"/> </view> </view> </Mask> js 逻辑: uni.setStorageSync('isGuide', true) //存储本地,只弹出一次的逻辑 // 新手引导初步下一步逻辑 clickToNext(){ this.guideNumber +=1 if(this.guideNumber == 6){ uni.setStorageSync('isGuide', true) this.showGuide = false; } }, less .maskGuide{ position: relative; width: 100vw; height: 100vh; .tl-img-1{ position: absolute; top: 48rpx; left: 20rpx; width: 584rpx; height: 230rpx; image-rendering: -webkit-optimize-contrast; } .tl-img-2{ position: absolute; top: 174rpx; left: 20rpx; width: 646rpx; height: 230rpx; image-rendering: -webkit-optimize-contrast; } .tl-img-3{ position: absolute; top: 40rpx; right: 0; width: 630rpx; height: 308rpx; image-rendering: -webkit-optimize-contrast; } .tl-img-4{ position: absolute; top: 240rpx; right: 10rpx; width: 604rpx; height: 112rpx; image-rendering: -webkit-optimize-contrast; } .tl-img-5{ position: absolute; top: 164rpx; right: 35rpx; width: 684rpx; height: 1048rpx; image-rendering: -webkit-optimize-contrast; } } 以上是目前想到的一个实现方案,如果有其他实现方案,欢迎大家补充。共勉! [图片]
2022-09-02 - 小程序端性能监控(1)
微信小程序前端性能监控(1) 本文分为两篇,认识与使用 performance,阅读各大约10分钟 01 打点: performance 是前端性能监控的API,小程序也实现了它。 首先我们回到一个古老的监控方法:Date.now(),用它打点行么? [图片] 图示:W3C提供的一段代码示例 回答当然是可以,那它与 performance 的区别在哪,为什么现在不推荐这种方式了? 首先就是精度问题,我们知道时间是个无穷小数,时间原点及精度取舍是不同的。有兴趣了解时间起源等更深入知识的小伙伴可以到文章结尾获取链接。 [图片] 图示:获取精度示例 最重要的是它提供了抓取各时间节点的API,定义了专用于测试的时间原点,及浮点数达到微秒级别的精确度等。Date.now() 时间戳可以衡量获取资源所需的时间,但是它不能分解页面加载在各个阶段花费的时间。此外,脚本无法轻松衡量获取标记中描述的资源所花费的时间。 大多系统运行一个守护程序定期同步时间,通常15-20min调整几毫秒,这个速率大约10S间隔的值会有1%的误差。而performence是恒定的速率,它定义了navigationStart,performance.timing.navigationStart + performance.now() 约等于 Date.now()。 02 基础API的认识: 在控制台打印 performance 如下: [图片] 图示:performance API memory 内存相关 jsHeapSizeLimit 内存大小的限制。 totalJSHeapSize 总内存的大小。 usedJSHeapSize 可使用的内存的大小。 注:如果 usedJSHeapSize 大于 totalJSHeapSize的话,那么就会出现内存泄露的问题,因此是不允许大于该值的。 navigation 页面的来源信息 redirectCount:如果有重定向,页面通过几次重定向跳转而来,默认为0 type:该值的含义表示的页面打开的方式。默认为0. 可取值为0、1、2、255这个值在实际项目中蛮实用,它可以判断来源页的跳转方法例如:手机触发返回,它的值为2 0:正常进入该页面(非刷新、非重定向)。 1:通过 window.location.reload 刷新的页面。如果我现在刷新下页面后,再来看该值就变成1了。 2:通过浏览器的前进、后退按钮进入的页面。如果我此时先前进下页面,再后退返回到该页面后,查看打印的值,发现变成2了。 255:非以上的方式进入页面的。 onresourcetimingbufferfull 回调函数 浏览器的资源时间性能缓冲区满了执行的回调 timeOrigin 时间戳它是一系列时间点的基准点,精确到万分之一毫秒。该值是动态的,刷新下,该值是会发生改变的。 timing 各时间点的集合 connectEnd:HTTP完成建立连接的时间(完成握手)。如果是持久链接的话,该值则和fetchStart值相同,如果在传输层发生了错误且需要重新建立连接的话,那么在这里显示的是新建立的链接完成时间。 connectStart:HTTP 开始建立连接的时间,如果是持久链接的话,该值则和fetchStart值相同,如果在传输层发生了错误且需要重新建立连接的话,那么在这里显示的是新建立的链接开始时间。 domComplete:DOM树解析完成,且资源也准备就绪的时间。Document.readyState 变为 complete,并将抛出 readystatechange 相关事件。 domContentLoadedEventEnd:DOM解析完成后,网页内资源加载完成的时间。 domContentLoadedEventStart:DOM解析完成后,网页内资源加载开始的时间。 domInteractive:完成解析DOM树的时间(只是DOM树解析完成,并没有开始加载页面资源)。 domLoading:开始解析渲染DOM树的时间。 domainLookupEnd:DNS域名查询完成的时间,如果使用了本地缓存或持久链接,该值则与fetchStart值相同。 domainLookupStart:DNS域名查询开始的时间,如果使用了本地缓存或持久链接,该值则与fetchStart值相同。 fetchStart:准备好使用http请求抓取文档的时间(发生在检查本地缓存之前)。 loadEventEnd:load事件的回调函数执行完毕的时间,如果没有绑定load事件,该值为0 loadEventStart:load事件发送给文档。也即load回调函数开始执行的时间,如果没有绑定load事件,则该值为0 navigationStar:同一个浏览器上一个页面卸载结束时的时间戳。如果没有上一个页面的话,那么该值会和fetchStart的值相同 redirectEnd:最后一个HTTP重定向完成时的时间戳。如果没有重定向或者重定向到一个不同的源,该值也返回为0 redirectStart:该值的含义是第一个http重定向开始的时间戳,如果没有重定向或者重定向到一个不同源的话,那么该值返回为0 requestStart:HTTP请求读取真实文档开始的时间,包括从本地读取缓存,链接错误重连时。 responseEnd:HTTP响应全部接收完成时的时间(获取到最后一个字节)。包括从本地读取缓存。 responseStart:开始接收到响应的时间(获取到第一个字节的那个时候)。包括从本地读取缓存。 secureConnectionStart:HTTPS 连接开始的时间,如果不是安全连接,则值为 0 unloadEventStart:前一个页面unload的时间戳,如果没有前一个页面,那么该值为0 unloadEventEnd:和 unloadEventStart 相对应,返回是前一个网页unload事件绑定的回调函数执行完毕的时间戳。 拓展学习 W3C Web Performance:https://www.w3.org/TR/resource-timing-2/#cross-origin-resources Web Performance Working Group:https://www.w3.org/webperf/ Chrome Web Fundamentals:https://developers.google.cn/web/fundamentals/performance/navigation-and-resource-timing chrome.loadTimes() API:https://developers.google.cn/web/updates/2017/12/chrome-loadtimes-deprecated#requesttime MDN Performence API:https://developer.mozilla.org/zh-CN/docs/Web/API/Performance MDN Timing-Allow-Origin API:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin Unix time:https://en.wikipedia.org/wiki/Unix_time Performance Navigation Timing:https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming Resource Timinghttps://www.w3.org/TR/resource-timing-2/#cross-origin-resources
2022-05-18 - 微信小程序运行性能注意点
小程序的运行时性能直接决定了用户在使用小程序功能时的体验。如果运行时性能出现问题,很容易出现页面滚动卡顿、响应延迟等问题,影响用户使用。如果内存占用过高,还会出现黑屏、闪退等问题。 1.控制WXML节点数量和层级 建议一个页面 WXML 节点数量应少于 1000 个,节点树深度少于 30 层,子节点数不大于 60 个。太大的 WXML 节点树会增加内存的使用,样式重排时间也会更长,影响体验。 2.避免滥用image组件的 widthFix/heightFix模式,控制图片资源的大小。 这种模式会在图片加载完成后,动态改变图片的高度或宽度。图片高度或宽度的动态改变,可能会引起页面内大范围的布局重排,导致页面发生抖动,并造成卡顿。 3.合理使用的setData setData 应只用来进行渲染相关的数据更新。用 setData 的方式更新渲染无关的字段,会触发额外的渲染流程,或者增加传输的数据量,影响渲染耗时。 不要过于频繁调用setData,应考虑将多次setData合并成一次setData调用;与界面渲染无关的数据最好不要设置在data中,可以考虑设置在page对象的其他字段下。对于列表来说,可以利用setData进行列表局部刷新。 4.避免不当的使用onPageScroll 每一次事件监听都是一次视图到逻辑的通信过程,所以只在必要的时候监听pageSrcoll。避免在 scroll 事件监听函数中执行复杂逻辑。 5.合理的利用缓存 利用storage API, 对变动频率比较低的异步数据进行缓存,二次启动时,先利用缓存数据进行初始化渲染,然后后台进行异步数据的更新,这不仅优化了性能,在无网环境下,用户也能很顺畅的使用到关键服务。 6.采用独立分包技术 提升体验最直接的方法是控制小程序包的大小。目前很多小程序主包+子包的方式,这对用户停留时间比较短的场景中,体验不是很好,且浪费了部分流量。 可以采用独立分包技术,区别于子包,和主包之间是无关的,在功能比较独立的子包里,使用户只需下载分包资源。 7.使用自定义组件 自定义组件的更新只在组件内部进行,不受页面其他不能分内容的影响。各个组件也将具有各自独立的逻辑空间。每个组件都分别拥有自己的独立的数据、setData调用。
2022-05-28 - Canvas 2d接口绘制问题踩坑总结
微信不再支持之前的旧Canvas接口,都升级到了2d,导致之前绘制海报的功能无法正常使用,这边进行了修正,把过程遇到的坑记录下。主要碰到的几个问题如下: 1、迁移到新接口; 新接口采用了不同的接入方式,可以参考迁移指南:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/canvas-legacy-migration.html 这里要特别注意的是,导出Canvas到图片的时候: wx.canvasToTempFilePath({ canvas: this.canvas, // 这里一定不要弄错 success: () => { ... } }) 2、导出图片的时候,绘制的图片是空白的 导出图片之后,发现绘制的图片是空白的,文字和矩形是正常的。是因为Canvas 2d是采用同步绘制的方式,不需要调用draw方法,也不需要等上一步绘制完,所以导出图片之前,要等待一下,确定绘制都完成。加个Timeout就行。 setTimeout(() => { wx.canvasToTempFilePath({ canvas: this.canvas, success: () => { ... } }) }, 300); 3、绘制的文字、矩形被图片覆盖问题 绘制图片导出正常了,但是会出现后绘制的文字和矩形都被图片给覆盖遮住了。其实这个问题和第二个问题类似,也是因为同步绘制的关系。但是因为绘制图片需要等图片加载之后再绘制,会导致文字会先绘制。处理方式,在onload里绘制图片,绘制图片之后,再调用下一个绘制: 直接贴Taro的代码了。 [图片]
2022-06-24 - 如何优雅的做一个启动loading页?
一.背景需求及分析基于微信用户又有人跑来ask the question,emm,写了个简易版本开屏广告看看吧 🚺:小程序启动页有做过吗? 🚹:放在page 第一页,定时跳转完事, setInterval, page:['启动页'], onShow(){ wx.redirectTo}, 导航使用custom wx.redirectTo(这时候考虑页面栈的问题), 会出现HOME导航logo,那么使用 [图片] wx.hideHomeButton可以解决 🚺:斗地主小程序,初次进来会有启动页,再次进来就没有了? 🚹: wx.setStorageSync、app().globaldata 试试 这两个能力自己看咯,做个缓存机制就OK了,不知道斗地主啥效果,你自己完善吧。 二.效果图[图片] 三.代码片段https://developers.weixin.qq.com/s/x4CExcmQ7lAb 四.知识点参考链接小程序导航'Home'按钮知识库:https://developers.weixin.qq.com/community/develop/doc/000406fe6f41381173397478e5b809wx.setStorageSync:https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorageSync.html app().globaldata:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html TIPS:emm,ヾ(•ω•`)o,拿去吧你,emm
2022-06-29 - 云函数利用npm exceljs导出excel 1000个SKU带高清图片
[图片] 想要导出大量数据就得从腾讯云登录你得小程序云开发 CloudBase可以修改900秒得超时时间,也就是可以执行15分钟;这次导出1000个SKU用了10分钟; [图片] [图片] 执行了10分钟,导出了24m的文件 [图片] [图片] 不多说,熬了俩个通宵,以及各位大佬的指点总结出来的 直接上源码 // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init({ // API 调用都保持和云函数当前所在环境一致 env: cloud.DYNAMIC_CURRENT_ENV }) const db = cloud.database() //exceljs 安装:npm i exceljs const ExcelJS = require('exceljs'); //引入superagent 安装 :npm i superagent const superagent = require('superagent'); // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() //查询要生成表格的数据 集合名记得改 const dataList = await db.collection("user").where({ jsxj:true //自己改改 //突破100条数据限制 }).limit(1000).get() //获取查询到的数据 const data = dataList.data //新建一个工作簿 const workbook = new ExcelJS.Workbook(); //创建一个工作表 const worksheet = workbook.addWorksheet('Sheet 1'); //设置第一行的行高 worksheet.properties.defaultRowHeight = 152.1; //设置第一行的列宽 worksheet.properties.defaultColWidth = 24.95; //设置第一行的文字垂直居中 worksheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center' }; //设置第一行的文字大小加粗 worksheet.getRow(1).font = {size: 16, bold: true}; //创建表头信息 worksheet.columns = [{header:'图片',key:'id'},{header:'产品标题',key:'url'}]; //循环往工作表里加数据 for (let rowIndex in data) { const rowcontent = [] //获取图片链接 var urls = encodeURI(data[rowIndex].cpimg[0]+'/sf200') //获取urls的图片链接转化成Base64 const img2Base64 = await new Promise(async function (resolve, reject) { const url = urls; await superagent.get(url).buffer(true).parse((res) => { let buffer = []; res.on('data', (chunk) => { buffer.push(chunk); }); res.on('end', () => { const data = Buffer.concat(buffer); const base64Img = data.toString('base64'); resolve('data:image/png;base64,'+base64Img) } ); }); }) //把img2Base64的数据生成imageId2,并添加图片到工作表 const imageId2 = workbook.addImage({ base64: img2Base64, extension: 'png', }); //获取imageId2,修改上面工作表里的图片大小位置 worksheet.addImage(imageId2, { tl: { col: 0, row: rowIndex-1+2}, ext: { width:200, height:200 }, editAs: 'undefined' }); //因为第一行是图片,所以这里传一个第一行的空值 rowcontent.push("") rowcontent.push(data[rowIndex].cpname) //更新表格 worksheet.addRow(rowcontent); } //生成表格 const buffer = await workbook.xlsx.writeBuffer(); //上传到云存储 return await cloud.uploadFile({ cloudPath: 'nhb/' + Date.now() + '.xlsx', fileContent: buffer, }) }
2022-03-24 - 由一次分享引发的生产事故
~ 由一次分享引发的生产事故 ~ ~ 小程序开发笔记来啦,为你们加油ヾ(◍°∇°◍)ノ゙每天进步一点点, 01、场景今天有用户反馈,挑战答题小程序一个细节问题 这几天参与了一个答题活动的制作,在答题活动方案中,有一个细节就是分享可以获得积分 具体规则如下 [图片] 这上面有个具体的规则是邀请1个用户得1分,每日限得3分 我在开发的时候封装了一个分享链接的生成逻辑,这样每个页面都可以直接复用,具体代码如下所示 最后通过小程序右上角,系统分享出去 [图片] ~ [图片] ~ 但是在实际测试的时候缺发现问题了 ~ [图片] ~ 正常情况下,后面拼接一个fromOpenid就对了,但是这里却反复的不断拼接,导致实际拼接的fromOpenid就不符合预期的逻辑了 ~ 其实这个问题就是云函数写的很低级的错误,云函数并不是每次都重置data,这样就造成了,这个data会不断的拼接导致这个path会越来越长, 02、改造方案其实要改造这个地方十分容易 [图片] ~ 在这里生成path的时候不需要拼接即可,但是要真正理解这个问题,还是要从原函数的原理出发 03、参考文章 ~ 使用云函数切记不要再export 之外定义全局变量.? - 微信开放社区 https://developers.weixin.qq.com/community/develop/article/doc/00068a06cb8340524a7aaa89c51413 ~
2022-04-07 - 投票评选活动小程序复盘
本文初写于2022-01-11,更新于2022-01-12 云开发搭建投票活动小程序 ~ 今天9:30分 历时一周开发的投票活动小程序迎来了第一波大考,为了迎接这次大考我做了如下几个工作 这是我做答题活动沿袭过来的经验 1、充值 本次选用的是云开发的按量付费服务,考虑到日活能达到10000+,提前充值20元,以备不时之需 [图片] 2、购买云开发的资源套餐包,具体可根据实际场景购买,由于云开发资源包第一次购买是有优惠的 具体花费如下 1)100GB CDN资源包 2)100万 GBs的云函数资源包 3)3000万读,1500万写的数据库资源包 分别消费为4.5,9.9,15元 ~ [图片] ~ [图片] 3、设置集合索引 将小程序中涉及的高频查询场景设置必要的索引,因提高查询的效率 比如投票明细集合 设置索引 为 historys_openid_today_index 用于查询用户每天是否投过哪些候选人 ~ [图片] ~ 在活动的过程中,会不断分享本次的一些数据 ~~~~ 我在前面写过3个优化的场景,唯独漏了一个场景4,那就是CDN,今天早上醒来,收到欠费的推送我就明白了 [图片] ~ 大家看上图就知道,CDN消费了130多,本来是期望用云开发减少开支的,没有达到预期的效果,所以现在补充一条最重要的一点 优化4 1)图片压缩,将涉及到的图片素材尽量压缩,在保证可辨识的情况下图片压缩 2)将图片找靠谱图床停靠 最终针对CDN消费太大的问题,我今天也花了一天的时间来优化 我描述下今天的方案历程 1、方案1就是将图片素材压缩,因为我发现用户给我的图片素材实在是太大了,之前大意了,以为买了CDN套餐就万事大吉了; 但是我发现这个方案升级后,依然没有改变CDN流量大的现状,如下图所示 [图片] 2、我在下午18:30左右将云存储的图片迁移到我的七牛云,CDN的流量马上降下来了,但是这并不解决问题,只是将费用转移了,最后还是要掏钱 最后不得已按照群里给的提示,找到白嫖图床的方案 [图片] ~ 实不相瞒,目前找的图床是我平时经常用的产品,也是我最大的收获,我一直使用这个产品,但是之前没有想到他们竟然可以作为图床,而且不会存在防盗链,不能访问的问题, 我使用的图床就是 https://yiban.io/ [图片] ~ 具体怎么用的我就不展开细讲了。 又是一个日活过万的小场面 [图片] ~
2022-01-12 - 小游戏资质提交审核指引Q&A
小游戏资质提交审核指引 温馨提醒:微信公众平台的账号名称是该账号的品牌表现,小游戏账号命名需符合平台规范。如需提前了解,或查询你的小游戏未符合平台规范 原因,可点击此处查阅平台命名规范 一、资质提交入口: 1.微信公众平台 -> 首页 -> 小程序发布流程 -> 小程序备案 -> 选择游戏情况 -> 资质提交(首次提交资质材料) [图片] 2.微信公众平台 -> 首页 -> 菜单栏左下角 -> 账号设置 -> 游戏设置 -> 资质管理 -> 前往管理(首次or后续更新资质材料)[图片] 二、主体迁移:微信公众平台 -> 首页 -> 菜单栏左下角 -> 账号设置 -> 基本设置 -> 主体信息 -> 小程序主体变更 -> 提交资质审核申请 [图片] 注:审核提交信息后预计1-2个工作日内处理完毕,审核请留意微信公众平台通知中心的通知。 说明:游戏资质文档规范及示例 一、各资质文档基本要求: (1)所有游戏需提交:《游戏自审自查报告》、《著作权自我声明》、《代备案授权书》 文档规范要求:上传文件,非个人主体请务必加盖清晰规范账号主体公章,个人主体请在落款处清晰规范签署个人签名并捺指印 查看示例: 《游戏自审自查报告》、《著作权自我声明-非个人主体》、《著作权自我声明-个人主体》、《代备案授权书-非个人主体》、《代备案授权书-个人主体》 (2)选填材料一个《计算机软件著作权登记证书》 文档规范要求:上传【原件或加盖著作权人鲜章的复印件】之扫描件,复印件务必清晰规范加盖著作权人公章或著作权人签名 查看示例:《计算机软件著作权登记证书》 注:游戏名称含有“软件”、“人名”、“英文”,《计算机软件著作权登记证书》为必填材料。 (3)牌类游戏需提交:《计算机软件著作权登记证书》、《网络游戏出版物号核发单》、《产品合规报告》、《产品运营报告》、《内容一致承诺函》、《关于使用微信支付服务的合法性承诺书》、《棋牌类网络游戏经营自查报告》、《游戏自审自查报告》、《著作权自我声明》、《代备案授权书》 文档规范要求:上传【原件或复印件】之扫描件,复印件非个人主体请务必加盖清晰规范账号主体公章,个人主体请清晰规范签署个人签名 查看示例:《计算机软件著作权登记证书》、《网络游戏出版物号核发单》、《产品合规报告》、《产品运营报告》、《内容一致承诺函》、《关于使用微信支付服务的合法性承诺书》、《棋牌类网络游戏经营自查报告》、《游戏自审自查报告》、《著作权自我声明-非个人主体》、《代备案授权书-非个人主体》 (4)开通虚拟支付游戏需提交:《网络游戏出版物号核发单》、《计算机软件著作权登记证书》、《游戏自审自查报告》、《内容一致承诺函》、《著作权自我声明》、《代备案授权书》 《网络游戏出版物号核发单》文档规范要求: 上传【原件】之扫描件 查看示例:《网络游戏出版物号核发单》 《计算机软件著作权登记证书》文档规范要求: 上传【原件或加盖著作权人鲜章的复印件】之扫描件,复印件务必清晰规范加盖著作权人公章或著作权人签名 查看示例:《计算机软件著作权登记证书》 《游戏自审自查报告》文档规范要求: 上传文件,请务必加盖清晰规范账号主体公章 查看示例: 《游戏自审自查报告》 《内容一致承诺函》文档规范要求: 上传文件,请务必加盖清晰规范账号主体公章 查看示例:《内容一致承诺函》 《著作权自我声明》文档规范要求: 上传文件,非个人主体请务必加盖清晰规范账号主体公章,个人主体请在落款处清晰规范签署个人签名并捺指印 查看示例:《著作权自我声明-非个人主体》、《著作权自我声明-个人主体》 《代备案授权书》文档规范要求: 上传文件,非个人主体请务必加盖清晰规范账号主体公章,个人主体请在落款处清晰规范签署个人签名并捺指印 查看示例:《代备案授权书-非个人主体》、《代备案授权书-个人主体》 (5)文化互动类目需提交:2个,《商标注册证》、《游戏自审自查报告》 《商标注册证》文档规范要求: 文档规范要求:上传【原件或复印件】之扫描件,复印件请务必加盖清晰规范商标注册人公章,商标注册人为个人请清晰规范签署个人签名 查看示例:《商标注册证》 《游戏自审自查报告》文档规范要求: 上传文件,非个人主体请务必加盖清晰规范账号主体公章,个人主体请在落款处清晰规范签署个人签名 查看示例: 《游戏自审自查报告》 (6)各个文件的格式、数量和大小要求 文件格式: 《网络游戏出版物号核发单》及《网络游戏出版物号核发单》授权书格式为 JPEG、JPG 《计算机软件著作权登记证书》文件为 JPEG、JPG、PNG、BMP、GIF、PDF 《计算机软件著作权登记证书》授权书为 JPEG、JPG、PNG、BMP 《游戏自审自查报告》文件为 JPEG、JPG、PNG、BMP、GIF 《内容一致承诺函》文件为 JPEG、JPG、PNG、BMP、GIF 《关于使用微信支付服务的合法性承诺书》文件为 JPEG、JPG、PNG、BMP 《棋牌类网络游戏经营自查报告》文件为 JPEG、JPG、PNG、BMP 《著作权自我声明》文件为 JPEG、JPG、PNG、BMP 《代备案授权书》文件为 JPEG、JPG、PNG、BMP 《产品合规报告》文件为 PDF 《产品运营报告》文件为 PDF 文件大小: 《网络游戏出版物号核发单》及《网络游戏出版物号核发单》授权书单个文件大小:≤ 200KB 《计算机软件著作权登记证书》及《计算机软件著作权登记证书》授权书单个文件大小:≤ 2000KB 《产品合规报告》、《产品运营报告》、《游戏自审自查报告》和《内容一致承诺函》大小不超过5M 《软著自我声明》、《代备案授权书》、《关于使用微信支付服务的合法性承诺书》和《棋牌类网络游戏经营自查报告》文件大小不超过2M 文件数量: 《网络游戏出版物号核发单》文件限制最多1张(多于1张请按顺序自行合并) 《网络游戏出版物号核发单》授权书限制最多2张(多于2张请按顺序自行合并) 《计算机软件著作权登记证书》限制最多1张(多于1张请按顺序自行合并) 《计算机软件著作权登记证书》授权书限制最多2张(多于2张请按顺序自行合并) 二、关于《计算机软件著作权登记证书》: (1)《计算机软件著作权登记证书》著作权人:提审软著证书的著作权人需与版号著作权人保持一致 《计算机软件著作权登记证书》著作权人说明示例图: [图片] (2)《计算机软件著作权登记证书》颁发日期:《计算机软件著作权登记证书》的颁发日期需在版号证书颁发日期前 《计算机软件著作权登记证书》颁发日期说明示例图: [图片] (备注:《计算机软件著作权登记证书》颁发日期为2015年5月6日,《网络游戏出版物号核发单》颁发日期为2016年11月8日) 三、关于各资质文档刊载游戏名称:各资质文件中的游戏名称,需与提审游戏名称保持完全一致 游戏名称一致说明示例图: [图片] 四、关于授权书: (1)提交入口:登录微信公众平台(mp.weixin.qq.com),进入公众平台菜单栏左下角->账号设置->游戏设置->资质管理->前往管理-> 在《授权书》入口上传相关授权书,该入口支持多个文档上传 [图片] (2)应用场景: 请针对小游戏资质软著授权、小游戏品牌合作等素材露出、使用他人的商标或IP等场景上传相关授权书及授权人的权利证明,包括但不限于著作权授权(不限于美术作品著作权、文字作品著作权、音乐作品著作权、计算机软件著作权);版号、备案信息中的运营单位授权他人发布小游戏;使用文学作品或影视作品名称或内容的小游戏;使用他人商标的小游戏;品牌联合推广等。 示例文档:《著作权授权书》、《运营授权书》、《商标授权书》 特别说明:若《网络游戏出版物号核发单》运营单位、《计算机软件著作权登记证书》著作权人与提审主体不一致,即《网络游戏出版物号核发单》运营单位委托他人发布小游戏的,请在《授权书》入口上传《计算机软件著作权登记证书》著作权人、《网络游戏出版物号核发单》运营单位、向提审主体出具的多份运营授权书。授权链条示例拆解,详见以下图表: [图片] [图片] 五、规范要求: (一)单份授权书 (1)明确标明授权人与被授权人准确名称 (2)写明授权作品的基本信息(软件名称及简写、版本号,计算机软件著作权登记证书登记号) (3)明确标明授权范围和期限 (4)授权方的盖公章或亲笔签名(个人) (5)授权书资质文件不得超过有效期 (二)多份授权书 (1)前后几份授权书之间需要有连续性 (2)在后授权书的授权范围不能超过在先授权书 (3)在后授权书的授权时间不能超过在先授权书 (4)注明是否有转授权的权利 文档规范要求:上传文件,务必加盖公章授权方盖公章或亲笔签名(个人) 查看示例:《著作权授权书》、《运营授权书》、《商标授权书》 六、其他易遗漏事项温馨提醒 (1)清晰:小游戏资质文件关键信息需清晰可见 (2)公章/签名:各资质文档需加盖公章或亲笔签名 附:如果你还不了解如何提审版本,请点击此处查看版本提审指引
2024-11-01 - 小程序模板消息能力调整通知
小程序模板消息能力在帮助小程序实现服务闭环的同时,也存在一些问题,如: 1. 部分开发者在用户无预期或未进行服务的情况下发送与用户无关的消息,对用户产生了骚扰; 2. 模板消息需在用户访问小程序后的 7 天内下发,不能满足部分业务的时间要求。 为提升小程序模板消息能力的使用体验,我们对模板消息的下发条件进行了调整,由用户自主订阅所需消息。 一次性订阅消息 一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。 [图片] (一次性订阅示例) 长期性订阅消息 一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。 目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。 调整计划 小程序订阅消息接口上线后,原先的模板消息接口将停止使用,详情如下: 1. 开发者可登录小程序管理后台开启订阅消息功能,接口开发可参考文档:《小程序订阅消息》 2. 开发者使用订阅消息能力时,需遵循运营规范,不可用奖励或其它形式强制用户订阅,不可下发与用户预期不符或违反国家法律法规的内容。具体可参考文档:《小程序订阅消息接口运营规范》 3. 原有的小程序模板消息接口将于 2020 年 1 月 10 日下线,届时将无法使用此接口发送模板消息,请各位开发者注意及时调整接口。 微信团队 2019.10.12
2019-10-13