- 做个优秀的小程序 - 体验评分
随着小程序的开发迭代,慢慢的我们会更加关注小程序的质量,今天来讲讲小程序的隐藏功能 -- 体验评分。 为什么需要体验评分 我们多做一点,就可以给用户更好的体验。(窃喜) 当然,做为开发者的我们,动动鼠标点一点就能帮助我们发现问题,是不是很愉快~~ 接下来我们来看看怎么使用体验评分? 怎么使用体验评分 体验评分的能力目前开放在【微信开发者工具 - 调试器 - Audits】 操作步骤:运行体验评分 - 一顿操作 - 获取体验报告 - 一顿优化。 (优化其实是一个圈,新代码加上之后也要继续关注哦~) [图片] 体验评分实践 我们用《小程序示例》来操作一波看看效果~ 01. 运行体验评分 使用开发者工具打开小程序,调试器区域切换到 Audits 面板,就一个“运行”按钮,点它。 [图片] 02.一顿操作 然后在工具上对小程序进行操作,比如:我点开了 “接口 - 媒体 - 音频 - 播放 ”。 [图片] 03.获取体验报告 操作完之后,点击“停止”,我们就可以获取到体验报告(简单~)。 [图片] 拿到报告之后,我们就可以看到总分 98,最佳实践 80。往下拉会有扣分的实际原因。 看第一条是 “发现正在使用废弃接口”,报告已经很清楚的告诉我们使用了废弃组件 audio,我们根据报告进行优化即可。 [图片] 04.一顿优化 按照报告优化完之后,我们可以继续进行体验评分功能确认优化是否完善。这是一个有用的圈圈⚪⚪⚪ 我们来讲几个优化过程中遇到的问题,咳咳咳 存在图片没有按原图宽高比显示 [图片] 在测试预览图片的时候,发现图片被挤了,体验评分告诉我们宽高比有问题,发现是 <image> 使用了默认的 mode (scaleToFill:缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素)。所以通过添加 mode="aspectFill" (缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。)来解决宽高比的问题。 [图片] [图片] 发现固定底部的可点击组件可能不在iPhone X安全区域内 [图片] 这个问题我们用手机测试是正常的,但是体验评分给了提示,所以就来看看实现方式是不是有问题: 原有方式:通过接口监听systemInfo.model.indexOf('iPhone X') 给 view 添加专属 class 官方推荐:官方推荐的方式是用 wxss 来兼容,不一定只有 iPhone X 下面会有安全区域 [图片] 发现正在使用废弃接口 [图片] 这个问题对一些老旧代码来说很有用,比如示例很久之前写的 auto-focus,由于基本没有改动,所以代码就一直保持不变。使用体验评分的时候检测到了这个属性是废弃属性,所以我们更换了可用属性 focus 来解决问题。 [图片] 体验评分总结 使用体验评分进行小程序示例的优化,有以下优点: 可以发现代码中使用的废弃api,避免后续踩坑根据实际操作发现相关耗时久的情况,预先发现体验问题合理的视觉/交互检测,提前做好兼容资源使用检测,用合适的资源做好小程序当然,体验过程中也有不足: 开发者工具不支持预览的 组件 / API 暂不支持体验评分(听说官方已经在努力推进啦)一起体验评分 如果你也在做小程序优化,欢迎使用体验评分来优化哦~ 预祝大家都拿 100婚 !!! [图片] 体验评分文档传送门 如果你有疑问,请在下方评论区留言给binnie,㊗️大家都没有bug,✌️✌️✌️
2020-12-04 - 关于数据预拉取wx.getBackgroundFetchData的疑问?
官方文档说调用wx.get...和wx.on...这两个,我的疑问是获取到数据后的处理代码,到底放在on里的1处,还是放在get里的2处?总不能像示例中的两处都写相同的处理代码吧(这样代码会执行2遍)? [图片] 这两个api的执行顺序是怎样的?难道wx.get...里的sucess这儿,不是总能获得正确的数据吗?(要不然还要wx.on...干嘛?)官方提供这个wx.on...的意义在哪? [图片] 而如果要把业务处理代码放在1处,文档中又说了,这个api并不总是会触发的... 所以现在搞不清楚,我获取数据后的处理代码,要写在1处还是2处呢?感觉这2处都不是100%能执行到的。 光一个预拉取就头疼了,我还想加上周期性更新呢,这个好像也会触发wx.on..如果加上就更晕了。 查阅了很多资料,都没有搞明白。网上的好多教程基本是照搬官方资料,希望有真正项目实践过的大神解惑,不甚感谢!
03-26 - 我在使用channel-video组件时, 明明是同一主体, 却提示"无法展示该视频号动态"
<channel-video class="video-content" finder-user-name="sphwZLoXeqfb9Jy" feed-id="export/UzFfAgtgekIEAQAAAAAAqOMloqtTnwAAAAstQy6ubaLX4KHWvLEZgBPEy4I0NSE8CYr-zNPgMJp96jT4WGVumxVAsYlqG0fD" autoplay binderror="videoErr"></channel-video> 视频号跟小程序是同一主体, 但是会提示"无法展示该视频号动态", 并且binderror返回 channel-video:fail 1416103 。 finder-user-name: "sphwZLoXeqfb9Jy" feed-id: "export/UzFfAgtgekIEAQAAAAAA5Hwi3ni78gAAAAstQy6ubaLX4KHWvLEZgBPE94JQLSEAWpv-zNPgMJrIyu5a6Dd-A8YR_3NjqVIZ" appid: "wx982831f6d506e862"
07-23 - 🎆我们开源啦 | 基于Skyline开发的组件库🚀
我们开源啦,希望可以给大家的开发之旅带来一些灵感。我后溪的小程序也都会基于这个组件库开发,并且会保持组件库的更新与维护。 我是第一次进行开源,肯定会有错漏,欢迎大家指正,我会以最快的时间响应修改。 Skyline UI 组件库 前言 Skyline 是微信小程序推出的一个类原生的渲染引擎,其使用更精简高效的渲染管线,性能比 WebView 更优异,并且带来诸多增强特性,如 Worklet 动画、手势系统、自定义路由、共享元素等。 使用这个组件库的前提是:通过微信小程序原生+skyline框架开发,所以目前我们不保证兼容webview框架(也就是电脑端与低版本的微信),但后续会进行系统性的兼容。 使用 Skyline UI前,请确保你已经学习过微信官方的 微信小程序开发文档 和 Skyline 渲染引擎文档 。 背景 随着Skyline 渲染引擎 1.1.0 版本发布,我们所运营的小程序也平稳的渡过了阵痛期,团队使用Skyline也越来得心应手,所以接下来,团队的开发重心全面偏向Skyline渲染框架,考虑有大量的UI交互重复,我们决定基于Skyline开发了这个UI组件库。 但团队力量有限,这个新生的组件可能有很多的不尽如人意,所以希望能以开源的方式吸引更多开发者使用Skyline框架,如果这个框架不适合你,也可以借鉴其思路。 Gitee Gitee仓库 在线预览 以下是目前两个使用该框架的小程序 SkylineUI组件库 [图片] NONZERO COFFEE [图片] 开始使用 UI库结构 Skyline UI组件库 依赖于以下四部分,具体使用参考以下的具体说明 utils工具库: 其中包含了UI库自定义的一个工具类SkyUtils,它包含了组件中所含的各种函数,非常重要。 各组件元素:sky-*(组件名) skywxss样式库:其中包含深浅色色彩、文字字体、布局等样式wxss 在小程序中引入 UI库 一、直接下载引入 点击下载组件包 将src下所有文件复制到您项目根目录下的components文件夹中,没有的话请自行新建。 二、npm引入 1.在小程序项目中,可以通过 npm 的方式引入 SkylineUI组件库 。如果你还没有在小程序中使用过 npm ,那先在小程序目录中执行命令: [代码]npm init -y [代码] 2.安装组件库 [代码]npm install jieyue-ui-com [代码] 3.npm 命令执行完后,需要在开发者工具的项目中点菜单栏中的 工具 - 构建 npm 两种引入方式的不同可能导致后续使用时,引用组件的路径不同,请注意区别 1.直接引入components文件夹内,引用地址通常是 ‘./components/‘ 2.npm引入,组件引用地址通常是’./miniprogram_npm/jieyue-ui-com/’ 如何使用 1.在app.js文件中初始化工具类,并且添加两个全局变量 [代码]// app.js App({ onLaunch() { ;(async ()=>{ // 全局注册工具类SkyUtils // 这里默认npm引用,地址为'./components/utils/skyUtils',如果是直接引用组件,地址可能是'./components/utils/skyUtils',后面不再说明 const SkyUtils = await import('./components/utils/skyUtils'); wx.SkyUtils = SkyUtils.default; // 初始化设备与系统数据 wx.SkyUtils.skyInit() // 小程序自动更新方法 wx.SkyUtils.versionUpdate() })() }, globalData: { sky_system:{}, sky_menu:{} }, }) [代码] 2.在app.wxss文件中引入样式文件 [代码]//wxss * _dark.wxss 是适配深色模式的色彩变量 @import '/miniprogram_npm/jieyue-ui-com/skywxss/skycolor.wxss'; @import '/miniprogram_npm/jieyue-ui-com/skywxss/skycolor_dark.wxss'; @import '/miniprogram_npm/jieyue-ui-com/skywxss/skyfontline.wxss'; @import '/miniprogram_npm/jieyue-ui-com/skywxss/skyfont.wxss'; @import '/miniprogram_npm/jieyue-ui-com/skywxss/skyother.wxss'; [代码] 3.page.json中引用组件 [代码]//page.json { "usingComponents": { "sky-text":"/miniprogram_npm/jieyue-ui-com/sky-text/sky-text" } } [代码] 4.页面中使用 [代码] // wxml <sky-text content="文本内容" max-lines="2" fade></sky-text> [代码] 5.其他组件具体使用请参考组件包中的redeme.md 适配深色模式 如果您在开发时,全部使用我们预设好的颜色变量,那么可以自动适配深色模式。 [代码].page{ background-color: var(--bg-l0); } [代码] [代码] <view style="background-color: var(--bg-l0)"></view> <view style="background-color: {{color}}"></view> [代码] [代码] Page({ data: { color: "var(--bg-l0)" } }) [代码]
01-09 - 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 - 微信小程序使用新版Canvas画布实现电子签名
布局文件: <view class="container column-me"> <view class="tips"> 请绘制清晰可见的签名并保存 </view> <canvas class="canvas" id="canvas" type="2d" disable-scroll="true" bindtouchstart="canvasStart" bindtouchmove="canvasMove" bindtouchend="canvasEnd" touchcancel="canvasEnd" binderror="canvasIdErrorCallback"></canvas> <view class='addBtn'> <button type="default" class='txt reset' bindtap="clickClear">重新签名</button> <button type="default" class='txt' bindtap="clickSave">保存签名</button> </view> </view> 样式文件: page { background: #fff; } .container { padding: 0 20rpx; height: 100vh; background: #fff; border-radius: 5px; } .canvas { width: 100%; flex: 1; box-sizing: border-box; margin-top: 10rpx; } .tips { display: flex; align-items: center; justify-content: center; text-align: center; color: #aaa; font-size: 20rpx; } .addBtn { display: flex; align-items: center; justify-content: center; width: 100%; background: #fff; z-index: 100; padding: 10rpx 0; } .addBtn .txt { text-align: center; width: 200rpx; font-size: 15rpx; border-radius: 100px; background: #0097fe; color: #fff; box-sizing: border-box; margin: 0 20rpx; padding: 10px; z-index: 100; } .reset { background: #fff !important; border: 1px solid #cccccc; color: #333333 !important; } 配置文件: { "usingComponents": {}, "pageOrientation": "landscape", "navigationBarTitleText": "医生签名" } JS文件: let http = require("../../utils/http.js"); // canvas 全局配置 var context = null; // 使用 wx.createContext 获取绘图上下文 context var mCanvas = null; //注册页面 Page({ /** * 页面的初始数据 */ data: { userId: '', //用户id hasDraw: false, //默认没有画 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ userId: options.scene, hasDraw: false, }) wx.createSelectorQuery() .select('#canvas') // 在 WXML 中填入的 id .fields({ node: true, size: true }) .exec((res) => { // Canvas 对象 const canvas = res[0].node mCanvas = res[0].node // 渲染上下文 context = canvas.getContext('2d') // Canvas 画布的实际绘制宽高 const width = res[0].width const height = res[0].height // 初始化画布大小 const dpr = wx.getWindowInfo().pixelRatio canvas.width = width * dpr canvas.height = height * dpr context.scale(dpr, dpr) //绘制背景 context.fillStyle = '#fff' context.clearRect(0, 0, canvas.width, canvas.height) context.fillRect(0, 0, canvas.width, canvas.height) }) }, onShow() { }, canvasIdErrorCallback: function (e) {}, //开始 canvasStart: function (event) { context.moveTo(event.touches[0].x, event.touches[0].y); }, //过程 canvasMove: function (event) { var x = event.touches[0].x; var y = event.touches[0].y; context.lineWidth = 4 context.lineCap = 'round' context.lineJoin = 'round' context.lineTo(x, y); context.stroke(); this.setData({ hasDraw: true, }); }, canvasEnd: function (event) { }, clickClear: function () { context.clearRect(0, 0, mCanvas.width, mCanvas.height); //清除画布 context.beginPath() //清空画笔 this.setData({ hasDraw: false, }); }, //保存签名 clickSave: function () { let that = this if (!this.data.hasDraw) { wx.showModal({ title: '提示', content: '签名内容不能为空!', showCancel: false }); return false; }; if (this.data.userId === undefined || this.data.userId === '') { wx.showModal({ title: '提示', content: '用户id为空,请重新扫码', showCancel: false }); return false; } //生成图片 wx.canvasToTempFilePath({ canvas: mCanvas, success: function (res) { http.upload({ url: '/admin/upload/upLoadFile', filePath: res.tempFilePath, name: 'file', formData: {}, callBack: function (uploadRes) { let res = JSON.parse(uploadRes) let url = res.data.url http.request({ url: "/doctor/home/updateSignature", method: "POST", noBody: true, data: { id: that.data.userId, image: url, }, callBack: (res) => { wx.showModal({ title: '温馨提示', content: '保存签名成功!', confirmText: '退出', showCancel: false, success(res) { if (res.confirm) { wx.exitMiniProgram({ success: function (res) { console.log(res) }, fail: function (err) { console.log(err) } }) } else if (res.cancel) { console.log('用户点击取消') } } }) } }) } }) } }) }, })
2023-08-04 - 如何实现一个简单的swiper效果
简单的siwper效果,又是逛社区发现老哥提的想要该效果,那么有需要,咱们就得上啊: 效果图: [图片] 上代码: wxml [代码]<view class="container"> <swiper duration="200" previous-margin="140rpx" next-margin="140rpx" bindchange="currentHandle" circular="{{true}}" class="swiper-out"> <block wx:for="{{punchList}}" wx:key="*this"> <swiper-item class="swp-item {{current === index ?'active-item': ''}}"> <view class="slide-image" style=" background: url({{item.bannerUrl}}) no-repeat center center;background-size: 100% 100%;" id="{{index}}"></view> </swiper-item> </block> </swiper> <view class="swp-dot"> <view class="square-12 m-r-8 {{current === index ?'active': ''}}" wx:for="{{punchList}}" wx:key="{{index}}"></view> </view> </view> [代码] JS [代码]const app = getApp() Page({ data: { punchList: [{ "bannerUrl": "https://qiniu-image.qtshe.com/1536067857379_122.png" }, { "bannerUrl": "https://qiniu-image.qtshe.com/1536068379879_115.png", }, { "bannerUrl": "https://qiniu-image.qtshe.com/1536068319939_230.png", }, { "bannerUrl": "https://qiniu-image.qtshe.com/1536068074140_695.png", }, { "bannerUrl": "https://qiniu-image.qtshe.com/1536068213758_796.png", }], current: 0 }, currentHandle(e) { let { current } = e.detail this.setData({ current }) } }) [代码] wxss [代码].container { display: flex; flex-direction: column; align-items: center; justify-content: space-between; height: 100vh; } .slide-image { height: 600rpx; width: 400rpx; margin-top: 20rpx; overflow: hidden; display: flex; flex-direction: column; align-items: center; justify-content: center; border-radius: 10rpx; } .swiper-out { width: 750rpx; height: 660rpx; margin-top: 60rpx; } .active-item .slide-image { box-shadow: 0 5rpx 20rpx 3rpx rgba(0, 0, 0, 0.15); } .swp-item { width: 400rpx; display: flex; flex-direction: column; align-items: center; padding-top: 4rpx; opacity: 0.6; } .active-item { opacity: 1; } .swp-dot { display: flex; justify-content: center; flex: 1; margin-top: 18rpx; } .m-r-8 { margin-right: 8rpx; } .m-l-8 { margin-right: 8rpx; } .square-12 { width: 12rpx; height: 12rpx; background-color: #d8d8d8; border-radius: 6rpx; transition: width 0.2s linear; } .active { background-color: #3c3c3c; width: 36rpx; transition: width 0.2s linear; } [代码] 代码放完了,看下效果吧。代码片段如下: https://developers.weixin.qq.com/s/DCK6HJmw7kaZ
2019-12-19 - movable-view中的图片在IOS上放大后模糊
movable-view中有个image,图片放在本地,图片本身不模糊。在Android中放大之后,图片由模糊迅速变为了清晰,而在IOS中放大之后,图片始终模糊。感觉在Android中,图片放大之后做了分级加载,而在IOS中没有这么处理。代码如下: <movable-area> <movable-view x="0" y="0" direction="all" scale="true" animation="true" inertia="true" scale-min="1" scale-max="5" out-of-bounds> <image class='map' mode='widthFix' src='{{mapSrc}}'> </image> </movable-view> </movable-area>
2018-08-17