- video组件无法去除小窗?
产品的需求是去除video自带的小窗模式,但是微信开发文档里面没有能去掉小窗的属性 [图片]
10-22 - 微信PC端“服务通知”通知卡片头部小程序logo显示异常?
[图片][图片] 图一为配置的模板,图二为微信PC端“服务通知”里的通知消息,logo显示异常。
10-15 - PC端微信,用户接收的模版消息,左下角显示的小程序LOGO不一样?
PC端微信,用户接收公众号的消息模版,部分用户的小程序展示LOGO未切换为最新的,这个是因为用户在LOGO切换前接收过模版消息,导致了PC本地有缓存,所以后面小程序更换LOGO后,这部分存了旧LOGO的用户,之后一直显示的也是旧LOGO吗? 错误的显示[图片] 正常的显示[图片] 查过模版消息的官方文档,里面没有控制展示LOGO的参数 [图片] 求助各位大佬,有啥好的办法,让这部分PC用户,重新读取展示新的小程序LOGO吗?
2022-06-22 - 如何解决小程序订阅消息不显示logo及小程序名称问题?
[图片] 发送的订阅消息 没有显示小程序logo 也没显示小程序名称 不知道怎么回事 从我的手机上看能看到一个默认的logo 还有右上角的三个点点 [图片] 同事的手机上只有三个点点 都没有默认logo [图片]
2022-10-31 - navigateTo传参数,参数中带有 "?"号和 "=" 号 参数会丢失
let src = "http://baidu/1234?id=8533185605"; wx.navigateTo({ url: '../now/now?src=' + src, }) 跳转后 src 收到为: http://baidu/1234 ?号后面的都丢失了, 应该是也当成 navigateTo 中的URL 中的问号了, 我用replace替换了 "?"号和 "=" 号 , 这样能收到了,但是我感觉这种方法不好. 有没有更好的方法传这种类型的参数呢?
2019-10-25 - MapContext.addVisualLayer(Object object)不生效?
[图片] [图片] [图片] 线上版本 2023-03 月还是正常的,现在不行了,真机调试跟预览均不行,这是啥原因???
2023-12-01 - 开发者工具更新不能打开要写入的文件?
开发者工具更新时,显示不能打开要写入的文件[图片]
2019-12-26 - wx.compressVideo在IOS压缩不起作用,基础库为3.0.0,手机型号如下,该怎么解决?
[图片]
2023-11-03 - scroll-view 组件部分属性及参数调整通知
由于安卓端 Webview 内核升级原因,自 2022 年 12 月 1 日起,scroll-view 组件将进行如下调整: 废弃在安卓端的 scroll-view 组件的 fast-deceleration 属性。废弃后该属性对应的交互将失效,并且退回至默认滚动行为。scroll-view 组件的其他属性可正常使用。废弃在安卓端的 ScrollViewContext.scrollTo 接口的 duration 及 velocity 参数。ScrollViewContext.scrollTo 接口的其他参数可正常使用。 即使在小程序不适配的情况下,上述调整不会影响用户的正常使用流程。如需实现更多的交互效果,建议使用 Skyline 渲染。 iOS 端不受本次调整影响。 微信团队 2022年11月11日
2022-11-11 - setData能否实现数组顶部插入数据
- 需求的场景描述(希望解决的问题) 现在页面有数据如下: list:[{0},{1},{2},{3}] 往下拉滚动加载到历史数据如下: history:[{4},{5},{6},{7}] 需求: 将history拼接到list前面,并且局部刷新(避免由于数据量大,影响渲染性能) list:[{4},{5},{6},{7},{0},{1},{2},{3}] - 希望提供的能力 查过api文档,setData目前只能更新某个item或者在尾部增加app数据。 所以,希望能实现数组顶部插入数据。
2018-12-20 - 期望?input支持焦点位置变更监听
需求,自定义了input输入框。 但是考虑到小程序pc端键盘输入,有左右箭头切换光标的操作,这种情况目前无法捕捉光标位置。
2023-01-17 - 使用 MobX 来管理小程序的跨页面数据
在小程序中,常常有些数据需要在几个页面或组件中共享。对于这样的数据,在 web 开发中,有些朋友使用过 redux 、 vuex 之类的 状态管理 框架。在小程序开发中,也有不少朋友喜欢用 MobX ,说明这类框架在实际开发中非常实用。 小程序团队近期也开源了 MobX 的辅助模块,使用 MobX 也更加方便。那么,在这篇文章中就来介绍一下 MobX 在小程序中的一个简单用例! 在小程序中引入 MobX 在小程序项目中,可以通过 npm 的方式引入 MobX 。如果你还没有在小程序中使用过 npm ,那先在小程序目录中执行命令: [代码]npm init -y [代码] 引入 MobX : [代码]npm install --save mobx-miniprogram mobx-miniprogram-bindings [代码] (这里用到了 mobx-miniprogram-bindings 模块,模块说明在这里: https://developers.weixin.qq.com/miniprogram/dev/extended/functional/mobx.html 。) npm 命令执行完后,记得在开发者工具的项目中点一下菜单栏中的 [代码]工具[代码] - [代码]构建 npm[代码] 。 MobX 有什么用呢? 试想这样一个场景:制作一个天气预报资讯小程序,首页是列表,点击列表中的项目可以进入到详情页。 首页如下: [图片] 详情页如下: [图片] 每次进入首页时,需要使用 [代码]wx.request[代码] 获取天气列表数据,之后将数据使用 setData 应用到界面上。进入详情页之后,再次获取指定日期的天气详情数据,展示在详情页中。 这样做的坏处是,进入了详情页之后需要再次通过网络获取一次数据,等待网络返回后才能将数据展示出来。 事实上,可以在首页获取天气列表数据时,就一并将所有的天气详情数据一同获取回来,存放在一个 数据仓库 中,需要的时候从仓库中取出来就可以了。这样,只需要进入首页时获取一次网络数据就可以了。 MobX 可以帮助我们很方便地建立数据仓库。接下来就讲解一下具体怎么建立和使用 MobX 数据仓库。 建立数据仓库 数据仓库通常专门写在一个独立的 js 文件中。 [代码]import { observable, action } from 'mobx-miniprogram' // 数据仓库 export const store = observable({ list: [], // 天气数据(包含列表和详情) // 设置天气列表,从网络上获取到数据之后调用 setList: action(function (list) { this.list = list }), }) [代码] 在上面数据仓库中,包含有数据 [代码]list[代码] (即天气数据),还包括了一个名为 [代码]setList[代码] 的 action ,用于更改数据仓库中的数据。 在首页中使用数据仓库 如果需要在页面中使用数据仓库里的数据,需要调用 [代码]createStoreBindings[代码] 来将仓库中的数据绑定到页面数据中,然后就可以在页面中直接使用仓库数据了。 [代码]import { createStoreBindings } from 'mobx-miniprogram-bindings' import { store } from './store' Page({ onLoad() { // 绑定 MobX store this.storeBindings = createStoreBindings(this, { store, // 需要绑定的数据仓库 fields: ['list'], // 将 this.data.list 绑定为仓库中的 list ,即天气数据 actions: ['setList'], // 将 this.setList 绑定为仓库中的 setList action }) // 从服务器端读取数据 wx.showLoading() wx.request({ // 请求网络数据 // ... success: (data) => { wx.hideLoading() // 调用 setList action ,将数据写入 store this.setList(data) } }) }, onUnload() { // 解绑 this.storeBindings.destroyStoreBindings() }, }) [代码] 这样,可以在 wxml 中直接使用 list : [代码]<view class="item" wx:for="{{list}}" wx:key="date" data-index="{{index}}"> <!-- 这里可以使用 list 中的数据了! --> <view class="title">{{item.date}} {{item.summary}}</view> <view class="abstract">{{item.temperature}}</view> </view> [代码] 在详情页中使用数据仓库 在详情页中,同样可以使用 [代码]createStoreBindings[代码] 来将仓库中的数据绑定到页面数据中: [代码]import { createStoreBindings } from 'mobx-miniprogram-bindings' import { store } from './store' Page({ onLoad(args) { // 绑定 MobX store this.storeBindings = createStoreBindings(this, { store, // 需要绑定的数据仓库 fields: ['list'], // 将 this.data.list 绑定为仓库中的 list ,即天气数据 }) // 页面参数 `index` 表示要展示哪一条天气详情数据,将它用 setData 设置到界面上 this.setData({ index: args.index }) }, onUnload() { // 解绑 this.storeBindings.destroyStoreBindings() }, }) [代码] 这样,这个页面 wxml 中也可以直接使用 list : [代码]<view class="title">{{list[index].date}}</view> <view class="content">温度 {{list[index].temperature}}</view> <view class="content">天气 {{list[index].weather}}</view> <view class="content">空气质量 {{list[index].airQuality}}</view> <view class="content">{{list[index].details}}</view> [代码] 完整示例 完整例子可以在这个代码片段中体验: https://developers.weixin.qq.com/s/YhfvpxmN7HcV 这个就是 MobX 在小程序中最基础的玩法了。相关的 npm 模块文档可参考 mobx-miniprogram-bindings 和 mobx-miniprogram 。 MobX 在实际使用时还有很多好的实践经验,感兴趣的话,可以阅读一些其他相关的文章。
2019-11-01 - navigateTo跳转带参长度没有限制么
使用navigateTo跳转页面带的参数为一万个字符,还是能跳转成功,不是会有长度限制么 [图片] [图片]
2023-11-06 - 小程序scroll-view翻转后 scroll-into-view的替代方案
背景 腾讯云医小程序有医患聊天会话的场景,由于会话场景存在查询历史消息的场景,小程序中按照常规思路加载历史消息时会出现跳动的问题;跳动的原因是由于在’顶部’插入dom,会使得后面的dom被往后面推,然后重新设置scroll-top或者scrol-into-view从而导页面出现跳动;我们尝试采用【 前端开发中聊天场景的体验优化】文章中的方案处理跳动的场景。该文章的核心观点将scroll-view元素通过设置css样式 transform: rotateX(180deg); 进行翻转,这样将历史消对应的dom结构放在尾部,当添加更多的历史消息(dom)时,由于dom是添加在尾部很优雅的绕过了插入历史消息跳动的场景。但是当我们按照这种方式实现后,发现scroll-view元素提供的scroll-into-view属性不好使了。因此有了本文通过计算scrollTop值设置scrollTop来达到相同目的。 复现该问题的小程序代码片段:代码片段 目前已经反馈给官方(官方已确认是内部组件实现暂不支持翻转的场景 基础知识介绍 计算scrollTop涉及到一些web和小程序的基础知识,后面针对这些基础点进行简单介绍 .scroll-into-view 微信小程序提供的scroll-view元素提供了属性 scroll-into-view,该属性的作用是可以将指定dom滚动到scroll-view可见区域内 [图片] 关于boundingClientRect 下图是MDN解释该属性时提供的,从下图中可以看到top/bottom/left/right的值是元素的左上角和右下角相对于视口左上角的水/垂直距离 [图片] 为了更深入理解这些值。给出了一个简易的demo(代码片段),获取实例元素的的boundingClientRect的值后,可以看到这些值是根据元素的border边界进行计算的 [图片] [图片] [图片] 值得注意的是,当元素处于一个滚动区域内部,left/top值是考虑滚动操作的即包含滚动距离的(参考MDN 另外,当我们把容器元素又或者元素自身设置 transform: rotateX/Y(180deg):不会导致top和bottom的值互换(left与right的值互换); 总会有这样的结论,当dom元素的宽度和高度不为0时,top值一定小于bottom值,left值一定小于right值 关于scrollTop 当一个容器的内容的高度大于其容器高度时,overflow不为visible/hidden时,则会出现滚动条。出现滚动条后,内容区域则可以滚动,此时scrollTop的值是容器可视区域的顶部到内容区域顶部的距离,见下面示意图。 [图片] 值得注意的是,滚动条出现在盒模型中的content区域,见下图滚动条不会覆盖padding/border部分。因此上面说到内容区域高度超过容器高度并不严谨,严谨的说法应该是超过容器的content区域的高度。 [图片] 如果此时给容器设置css样式: transform: rotateX(180deg); 即沿垂直方向翻转180度,scrollTop的值会发生变化吗。 下面我们看下实际的对比效果,为了方便查看滚动条的效果,给滚动条轨道(红色部分)以及滑块(黑色部分)添加了背景色,发现整个元素包括滚动条在内一并进行了翻转。 正常情况(左侧),应用翻转css样式(右侧) [图片] [图片] 翻转后的scrollTop值示意图 [图片] 通过计算scrollTop值来模拟scroll-into-view效果(针对scroll-view翻转的场景j) 由于boundingClinetRect的值是包含border边界的,因此当数据项包含padding,border等区域不会影响这里的计算过程,可以认为下面示意图中的数据项部分的边界是border边界; 由于滚动条是出现在content区域,因此容器元素的的border-top/padding-top不为0时,会影响计算流程,因此这里分为两种情况进行介绍: 2.1 假设scroll-view元素的的border-top/padding-top为0 2.2 假设scroll-view元素的的border-top/padding-top不为0 border-top/padding-top为0的情况 为了方便说明计算过程,我定义三种状态,初始态、中间态、最终态 示意图中的区域说明 白色背景的为视口, 绿色背景的是容器(scroll-view)的可视区域, 灰色区域是内容区域,并且内容区域的高度超过了容器的高度, 红色区域是一个数据项 [图片] 现在的目标是将数据项从初始态滚动到最终态即scroll-into-view的效果:border的上边界与可视区域上边界对齐 第一步:从初始态达到中间态 根据上面关于scrollTop的描述,这里如果scrollTop的值是targetDistance即数据项的底部到内容区域的底部的距离,就可以达到中间态,因此现在的目标是求targetDistance 初始状态的已知变量 初始状态下的的scrollTop值:currentScrollTop (由于容器发生翻转,所以scrollTop视觉上指向容器下方) 数据项的boundingClientRect.bottom为 itemBottom 容器的boundingClientRect.bottom为 contianerBottom 通过示意图很容易得出 [代码]targetDistance = currentScrollTop + (containerBottom - itemBottom) [代码] 第二步:从中间到达最终态 已知变量:容器高度:containerHeight、数据项高度:itemHeight 最终态是数据项的顶部距离容器顶部,从示意图中看到中间态到最终态的scrollTop是减少了的,减少的值其实就是cotainerHeight - itemHeight 经过第一步和第二步我们就可以得到scrollTop的计算公式 [代码]let itemScrollTop = currentScrollTop + containerBottom - itemBottom itemScrollTop -= (containerHeight - itemHeight) => itemScrollTop = currentScrollTop + containerBottom - itemBottom - (containerHeight - itemHeight) [代码] border-top/padding-top不为0的情况 [图片] 根据上面第一种情况的介绍的思路,很容易得到下面结果,不再赘述(X 就是容器padding-top + border-top的值) [代码]let itemScrollTop = currentScrollTop + containerBottom - itemBottom - X itemScrollTop -= (containerHeight - itemHeight - X) => itemScrollTop = currentScrollTop + containerBottom - itemBottom - X - (containerHeight - itemHeight - X) => itemScrollTop = currentScrollTop + containerBottom - itemBottom - (containerHeight - itemHeight) [代码] 【结论】两种情况最终的计算过程是一样的,因此在实现的过程中不需要进行区分 代码实现 代码片段见:https://developers.weixin.qq.com/s/y1X11dmr7AqC 视图层代码 [代码]{{item.content}} #scroll-view { position: absolute; top: 50px; bottom: 50px; width: 100%; background-color: rgba(0, 0, 0, 0.1); // 关键case transform: rotateX(180deg); } [代码] 逻辑层核心代码 [代码]scrollTo () { const itemId = '#item_id_50' const containerId = '#scroll-view' Promise.all([this._queryBoundingClient(itemId), this._getScrollInfo(containerId)]) .then((res = [[[{}]], {}]) => { const [[[ { bottom: itemBottom, height: itemHeight }]], { bottom: containerBottom, scrollTop, height: containerHeight }] = res let itemScrollTop = containerBottom - itemBottom + scrollTop itemScrollTop -= (containerHeight - itemHeight) this.setData({ scrollTop: itemScrollTop }) }) }, _queryBoundingClient (selector) { // 获取目标dom的相关位置/尺寸信息 return new Promise(resolve => { const query = this.createSelectorQuery(); query.selectAll(selector).boundingClientRect(); query.exec(resolve); }) }, _getScrollInfo (idSelector) { // 用来获取容器层相关位置/尺寸信息 return new Promise(resolve => { const query = this.createSelectorQuery() query.select(idSelector).boundingClientRect() query.select(idSelector).scrollOffset() query.exec((res = [{}, {}]) => { const [{ top, bottom, height }, { scrollHeight, scrollTop }] = res const scrollInfo = { scrollTop, scrollHeight, top, bottom, height } resolve(scrollInfo) }) }) } [代码]
2023-03-23 - 微信小程序使用自定义目录(文件路径)进行下载/保存 案例(fail permission denied 解决方案)
场景描述 最近项目中有一个需要把网络文件下载下来保存到本地,然后对下载的文件进行读取,待文件不再使用后把文件进行删除的需求。当然也类似的需求还有很多,比如把小程序中的临时图片/文件永久保存下来等等,都是对文件操作的典型场景。 常见问题 在以上场景的实现过程中可能会遇到各式各样的问题,以下是比较常见的几个: 不清楚文件应该保存到哪个目录下。 fail permission denied 文件权限问题。 使用同步函数不清楚怎么获取执行结果。 API提炼 提到文件操作我们会自然而然地想到了API中的FileSystemManager相关的API,我这里用到的函数有以下几个: 下载函数 wx.downloadFile(Object object) 异步函数: FileSystemManager.access(Object object) FileSystemManager.mkdir(Object object) 同步函数: FileSystemManager.accessSync(string path) FileSystemManager.mkdirSync(string dirPath, boolean recursive) 我对同样的业务逻辑分别分别尝试了异步和同步的两种不同的方案,下面我们用一个最简单的下载保存到本地的案例来切入正题。 案例实践 一:获取正确的文件目录路径 当然在保存文件之前我们先要解决一个小问题,那就是我们要保存到哪里?也就是我们自定义的目录。这里我们简单命名其为 [代码]//自定义缓存文件根路径 var rootPath = "......"; [代码] (当然你也可以命名成其他名字) 变量名字可以随便写,不过自定义路径可不能随便写,也不可以在下载的时候直接给一个path路径,否者就会抛出没有权限或找不到文件的异常。所以开发者并不是可以随意的决定自定义文件的路径,这里就不卖关子了,小程序API中有一个很容易被忽略的API, wx.env.USER_DATA_PATH是专门获取文件系统中的用户目录路径的常量值。 这就是我们在小程序中合法的可操作文件的根目录路径: [代码]rootPath = wx.env.USER_DATA_PATH; [代码] 好了到目前为止我们已经知道了我们该往里存储文件了。 定义一下我们下载文件的缓存目录 [代码]var cachePath = rootPath+"/cache"; [代码] 也就是说之后我们下载的文件都会保存到 /cache 目录下,我们在之后的代码中用到的目录路径均为此路径。 二:异步函数实现方案 我们先来用异步函数来实现一下下载保存的流程。 1 下载文件之前我们首先要判断当前目录是否存在,如果目录不存在我们就直接下载文件到该目录下就会抛出 fail permission denied [图片] 这是判断目录存在的代码 [代码] access() { return new Promise(function(resolve, reject) { let fm = wx.getFileSystemManager(); fm.access({ path: cachePath, success: function(res) { resolve(); }, fail: function(err) { resolve(err); } }); }); }, [代码] 2 如果目录真实存在那我们当然可以直接使用,如果目录不存在则需要开发者自己创建目录。 [代码] mkdir(){ return new Promise(function(resolve, reject) { let fm = wx.getFileSystemManager(); fm.mkdir({ dirPath: cachePath, recursive: true, success: function(res) { resolve(); }, fail: function(err) { resolve(err); } }); }); }, [代码] 代码执行完之后我可以验证一下目录是否如我们所愿被创建出来。 开发工具右上角的详情–>基本信息–>文件系统–>当前小程序文件系统根目录 [图片] 点击usr文件夹进入根目录 [图片] 执行完上面代码之后我们可以看一下 cache 文件夹确实已经存在了 [图片] 3 目录也存在了,万事具备只欠下载了 [代码] downloadFile() { let fileUrl = 'https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg'; wx.downloadFile({ url: fileUrl, filePath: cachePath + '/temp.png', success: function(res) { console.log('downloadFile success', res); }, fail: function(err) { console.log('downloadFile fail', err); } }); }, [代码] 那执行完下载的代码之后我们再来看看cache目录 [图片] 这就是我们刚刚下载的图片。 ok,异步的整个下载和文件创建流程就走完了。接下来我们来瞅瞅同步流程中有哪些需要我们注意的。 三: 同步方案 同步方案和异步方案的流程大体一致,都是先判断文件目录是否存在,若不存在则创建目录,存在则执行下载逻辑。 使用同步函数需要特别注意的是怎么去判断函数的执行结果,由于 FileSystemManager.accessSync(string path) FileSystemManager.mkdirSync(string dirPath, boolean recursive) 这两个同步函数没有直接给出任何的返回结果。那我们怎么知道目录是否存在、目录是否被创建成功了呢? 这里我们需要剑走偏锋一下,即利用同步函数抛出的异常来判断结果。 我们直接来看代码 [代码] accessSync() { return new Promise(function(resolve, reject) { let fm = wx.getFileSystemManager(); try { fm.accessSync(cachePath); resolve(); } catch (err) { resolve(err); } }); }, mkdirSync() { return new Promise(function(resolve, reject) { let fm = wx.getFileSystemManager(); try { fm.mkdirSync(cachePath, true); resolve(); } catch (err) { resolve(err); } }); }, [代码] 可以看到我们的代码中多了 try catch 的代码结构,因为同步方法中没有直接返回给我们可用的信息,那我们可以认为同步函数正常执行完的结果为true或success,而进入 catch 后则结果为false或fail亦或根据具体异常具体处理。我们利用同步函数来走一遍下载保存的流程。 [代码] // 同步函数流程 this.accessSync().then(function (err) { if (err) { return that.mkdirSync(); } }).then(function (err) { if (!err) { that.downloadFile() } }); [代码] 可以看到我们利用同步函数下载的图片。 [图片] 总结时刻 我们分别使用异步和同步函数完成了目录的创建和文件的下载等流程。在这个过程中我们特别需要注意几点: 操作文件的根目录是以 wx.env.USER_DATA_PATH 开头的。 使用自定义目录时一定主要不可直接使用,需要增加 判断目录存在、创建目录 两个步骤。 使用同步函数时的执行结果是通过抓取同步函数抛出的异常来进行判断的。在没有给出直接结果的时候要学会利用异常信息来达到目的。 在创建目录时如果该目录存在同样会抛出异常(fail file already exists),这时按照success逻辑继续往下执行即可。 异步方案中介绍了目录查看的步骤和方法,可自行验证。其中usr目录是开发者自定义目录根节点,tmp目录是小程序默认的缓存根节点。 结尾 叙述若有不对或不严谨之处还请不吝指正。
2019-10-31 - 操作本地数据库(SQLLite)
- 需求的场景描述(希望解决的问题) 保存列表数据到本地数据库,并进行频繁查询操作。因业务特殊性需求需要把数据保存到本地。 - 希望提供的能力 使用现有key value方式保存数据,担心对有查询性能影响。 可否放开操作H5原生sqlite数据库
2018-04-18 - 小程序中使用map。ios中@markertap 事件会穿透。安卓。app,微信开发工具都 正常。
https://ask.dcloud.net.cn/question/111637 在dcloud 提的bug,需反馈到小程序官方。看到有类似的bug反馈,为什么不解决呢?官方?
2020-12-05 - 为什么IOS下Map组件的marker点击事件会被覆盖在上层的view点击事件穿透触发?
map组件,覆盖在marker标记点的view组件,点击事件穿透触发了marker的点击事件,安卓系统不会穿透触发而IOS会。 demo代码片段:https://developers.weixin.qq.com/s/9M1qYYmt7tkl
2020-10-09 - 手把手教你避开组件cover-view的那些坑
案例背景: 最近在开发城市地铁图项目,具体功能有规划路线、定位最近地铁站、以及显示整个城市的地铁网状图等功能。根据需求,在实现的时候在地铁线路图上需要添加定位按钮及线路弹框来展示位置信息以及地铁站详情信息。 遇到的问题: 在地铁图调研初期,原计划实现渲染方案是采用svg来绘制,但是调研后发现小程序原生API不支持svg。同时,我们在开源中找到一个svg的框架库来实现绘制,但是开发初期发现遇到很多无法实现的需求和性能问题。在对开源库的代码跟踪后,发现绘制方案也是canvas的方式,于是我们决定使用原生canvas的方案来支持地铁图。但是呢,又遇到一些问题,那么我们来看看几个具体的点: 1) view在canvas上无法正常显示。 在canvas上使用view来添加图片和弹框时,发现图片以及弹框在canvas的下面,不能正常显示图片。 查看文档发现canvas、map、video等原生组件使用的是native实现的,默认显示在小程序的最上层,所以就把view换成cover-view或者cover-image。 使用view效果: [代码]<!-- 线路 -->[代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"sublines sublines-icon"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]image[代码] [代码]class[代码][代码]=[代码][代码]'sublinesIcon'[代码] [代码]src[代码][代码]=[代码][代码]"/static/img/ic_sublines.png"[代码][代码] [代码][代码]bindtap[代码][代码]=[代码][代码]'clickSublines'[代码] [代码]wx-if[代码][代码]=[代码][代码]"{{lineIconShow}}"[代码][代码]></[代码][代码]image[代码][代码]> [代码][代码]</[代码][代码]view[代码][代码]>[代码] [图片] 替换成cover-view效果: [代码]<!-- 线路 -->[代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]"sublines sublines-icon"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-image[代码] [代码]class[代码][代码]=[代码][代码]'sublinesIcon'[代码] [代码]src[代码][代码]=[代码][代码]"/static/img/ic_sublines.png"[代码][代码] [代码][代码]bindtap[代码][代码]=[代码][代码]'clickSublines'[代码] [代码]wx-if[代码][代码]=[代码][代码]"{{lineIconShow}}"[代码][代码]></[代码][代码]cover-image[代码][代码]> [代码][代码]</[代码][代码]cover-view[代码][代码]>[代码] [图片] 但是使用cover-view又遇到了层级和样式的问题。 2)canvas上使用cover-image添加图片,图片设置position:absolute;页面上的图片显示在canvas画线的下方,导致定位按钮不能正常使用。后来把position该换成fixed解决来层级的问题。效果如下所示: [代码].locationIcon {[代码][代码] [代码][代码]width: 3rem;[代码][代码] [代码][代码]height: 3rem;[代码][代码] [代码][代码]position: fixed;[代码][代码] [代码][代码]bottom: 3rem;[代码][代码] [代码][代码]left: 0.7rem;[代码][代码]}[代码][图片] 3)在页面上实现一个弹框时,根据UI图需要实现一个底边线和底边小三角形。通过border给块级元素设置底边线或者css实现三角箭头,单边border设置无效。最终采用了height为1px的cover-view或者图片来代替。 设置单边border效果: [代码]<!-- 起终点设置弹框 -->[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]"sdMark"[代码] [代码]style[代码][代码]=[代码][代码]'top:{{tapClient.y}}px;left:{{tapClient.x}}px;'[代码] [代码]wx-if[代码][代码]=[代码][代码]"{{sdMarkShow}}"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkContent'[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkItem'[代码] [代码]bindtap[代码][代码]=[代码][代码]'clickStart'[代码][代码]>设为起点</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkItem'[代码] [代码]bindtap[代码][代码]=[代码][代码]'clickEnd'[代码][代码]>设为终点</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkItem'[代码] [代码]bindtap[代码][代码]=[代码][代码]'clickStationDetail'[代码][代码]>站点详情</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]cover-view[代码][代码]>[代码] [图片] 修改后的代码: [代码]<!-- 起终点设置弹框 -->[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]"sdMark"[代码] [代码]style[代码][代码]=[代码][代码]'top:{{tapClient.y}}px;left:{{tapClient.x}}px;'[代码] [代码]wx-if[代码][代码]=[代码][代码]"{{sdMarkShow}}"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkContent'[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkItem'[代码] [代码]bindtap[代码][代码]=[代码][代码]'clickStart'[代码][代码]>设为起点</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'line'[代码][代码]></[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkItem'[代码] [代码]bindtap[代码][代码]=[代码][代码]'clickEnd'[代码][代码]>设为终点</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'line'[代码][代码]></[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]'sdMarkItem'[代码] [代码]bindtap[代码][代码]=[代码][代码]'clickStationDetail'[代码][代码]>站点详情</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-view[代码] [代码]class[代码][代码]=[代码][代码]"icon"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]cover-image[代码] [代码]class[代码][代码]=[代码][代码]'icArrow'[代码] [代码]src[代码][代码]=[代码][代码]'/static/img/ic_arrow.png'[代码][代码]></[代码][代码]cover-image[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]cover-view[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]cover-view[代码][代码]>[代码] 最终的效果: [图片] 踩坑总结:canvas层级较高,使用cover-view或者cover-image在canvas做操作。单边border相关的操作使用图片或者块级元素来代替。 查看相关API文档: cover-view相关文档:https://developers.weixin.qq.com/miniprogram/dev/component/cover-view.html 欢迎体验和吐槽:"腾讯位置服务-地铁图"插件:https://developers.weixin.qq.com/community/servicemarket/sq_ocVuQ4joORnwn_bzpxTd8Mq8wZ3g/service/detail/0008cc3058c5c8042dc89d7db54415
2019-07-17 - 使用微信API实现用户授权登录
小程序中经常需要获取用户的个人信息。为了保护用户的隐私,微信提供了OAuth2.0的授权机制,具体如何实现? 首先,在app.json文件中添加配置: json { "pages": [ "pages/index/index", "pages/logs/logs" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "WeChat", "navigationBarTextStyle": "black" }, "requiredBackgroundModes": ["audio"], "permission": { "scope.userInfo": { "desc": "你的描述" } } } 接下来,在需要进行授权登录的页面(例如index.js)中调用微信的login接口: javascript Page({ data: {}, onLoad: function () { wx.login({ success: res => { // 发送code到服务器换取openId等信息 console.log(res.code) } }) } }) 以上代码会弹出一个授权对话框,用户点击确认后,将会返回一个临时的code值。我们需要把这个code发送到自己的服务器,然后通过微信提供的API换取用户的openid和其他信息。 在实际开发过程中,你需要处理各种可能的异常情况,例如网络错误、用户拒绝授权等。 以上就是实现用户授权登录的基本步骤。
2023-12-12 - 官网让用View代替cover-view,但 view 组件没支持设置 marker-id属性?
<view marker-id="123">123</view> 这样写在开发者工具上不会有 marker-id 属性,这个能加上吗
2023-06-07 - map地图 markers标记的label属性textAlign设置居中在苹果正常,在安卓不居中?
label:{ content:resu.data[i].ww_title, fontSize:12, color:'#000000', bgColor:'#ffffff', padding:5, textAlign:'center' }
2020-11-05 - map组件中的marker上的自定义气泡(customCallout)中的元素无法添加点击事件吗?
[图片] 这个是ui给出的设计图, 在地图上点击标记需要在上方展示一个面板,并且其中有两个可点击的按钮, 这里的气泡我用的是基础库2.12.0中新添加的customCallout功能, 但是我发现无法给气泡中的元素添加点击事件, 是不支持, 还是说我的实现方法有问题? 以下是代码片段 https://developers.weixin.qq.com/s/or6YAzmU7gju
2020-08-13 - map circles radius 的单位是什么?
说明文档没有,Q&A中也没有查到。单位是米、千米、像素?还是什么?望告知一声,谢谢!
2017-02-20 - 小程序性能优化实践
小程序性能优化课程基于实际开发场景,由资深开发者分享小程序性能优化的各项能力及应用实践,提升小程序性能表现,满足用户体验。
10-09 - 【优化】利用函数防抖和函数节流提高小程序性能
大家好,上次给大家分享了swiper仿tab的小技巧: https://developers.weixin.qq.com/community/develop/article/doc/000040a5dc4518005d2842fdf51c13 [代码]今天给大家分享两个有用的函数,《函数防抖和函数节流》 函数防抖和函数节流是都优化高频率执行js代码的一种手段,因为是js实现的,所以在小程序里也是适用的。 [代码] 首先先来理解一下两者的概念和区别: [代码] 函数防抖(debounce)是指事件在一定时间内事件只执行一次,如果在这段时间又触发了事件,则重新开始计时,打个很简单的比喻,比如在打王者荣耀时,一定要连续干掉五个人才能触发hetai kill '五连绝世'效果,如果中途被打断就得重新开始连续干五个人了。 函数节流(throttle)是指限制某段时间内事件只能执行一次,比如说我要求自己一天只能打一局王者荣耀。 这里也有个可视化工具可以让大家看一下三者的区别,分别是正常情况下,用了函数防抖和函数节流的情况下:http://demo.nimius.net/debounce_throttle/ [代码] 适用场景 函数防抖 搜索框搜索联想。只需用户最后一次输入完,再发送请求 手机号、邮箱验证输入检测 窗口resize。只需窗口调整完成后,计算窗口大小。防止重复渲染 高频点击提交,表单重复提交 函数节流 滚动加载,加载更多或滚到底部监听 搜索联想功能 实现原理 [代码] 函数防抖 [代码] [代码]const _.debounce = (func, wait) => { let timer; return () => { clearTimeout(timer); timer = setTimeout(func, wait); }; }; [代码] [代码] 函数节流 [代码] [代码]const throttle = (func, wait) => { let last = 0; return () => { const current_time = +new Date(); if (current_time - last > wait) { func.apply(this, arguments); last = +new Date(); } }; }; [代码] [代码] 上面两个方法都是比较常见的,算是简化版的函数 [代码] lodash中的 Debounce 、Throttle [代码] lodash中已经帮我们封装好了这两个函数了,我们可以把它引入到小程序项目了,不用全部引入,只需要引入debounce.js和throttle.js就行了,链接:https://github.com/lodash/lodash 使用方法可以看这个代码片段,具体的用法可以看上面github的文档,有很详细的介绍:https://developers.weixin.qq.com/s/vjutZpmL7A51[代码]
2019-02-22 - wx.setPageStyle()这个东西有人会用吗?
[图片] wx.setPageStyle()可以改变里面的样式,但是我想知道怎么实现下面的这个 [图片]
2021-05-26 - 如何动态修改page{}样式?
请问如何动态修改*.wxss里面page{}样式呢?wxml里面也不可以改变page样式,只能改变某组件的样式,假如改变整个页面的背景,如何在js动态?
2017-12-06 - 小程序用户代码片段讲解
用户代码片段 场景: 此代码片段非彼代码片段。用户代码片段,这个功能是做什么用的呢?简单的说就是代码提示功能,用户通过自定义的方式,来将一些经常使用的代码封装成模板,从而的能够快速书写出来。不管你写什么代码,在编辑器肯定有提示功能,但是肯定会碰到一些代码是没有提示的,但是你又经常手敲或复制粘贴,就会降低了程序开发的效率,这时候用户代码片段就可以帮你解决这个问题。 打开微信开发者工具,找到文件-首选项-用户代码片段,你可以选择现有代码片段进行编辑或者新建代码片段,新建则键入文件名,按下Enter完成创建 [图片][图片] 成功后是这样一个文件,已经给你举了个例子 [图片] 参数说明: { //整个对象集合,你可以将你常用的模板全部放这一个对象里面,每个模板对象用逗号分隔 "Print to console": { //模板的名称,也是在你键入代码快捷键时右边的提示 "scope": "javascript,typescript", //片段用于的范围,在范围字段中添加代码段适用的语言的逗号分隔。如果范围为空或省略,则代码段将应用于所有语言。 "prefix": "log", //前缀,快捷键,触发的模板提示的关键词 "body": [ //正文,整个模板内容,后面细讲 "console.log('$1');", "$2" ], "description": "Log output to console" //说明,对代码片段的详细说明(可省略,如果description不写,默认会显示key键的内容) } } [图片] body内容说明: 1、$1,$2...表示制表位,$0表示最终光标位置,${1:label},${2:other}表示占位符,将连接具有相同ID的占位符,通过Tab键切换下一个光标位置。 2、\n 表示回车。 3、空格代表一个字符,tab为两个,主要用于代码缩进。 4、body 是一个数组,数组的每一项就是一行代码,所以如果你的代码是多行的话,就写成一个数组形式,如果项里还有双引号,需要在双引号前用进行转义。 5、变量提示,${变量,提示内容},如:${1,参数为String、Number} 6、枚举值提示,${变量|枚举值|},多个枚举值用英文逗号分隔,如:${1|barCode, qrCode|} 7、特殊变量, $变量名 如:$CURRENT_MONTH_NAME https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables 8、代码片段生成器:https://99cc.vip/public/tools/vscode_snippet/index.html 或 https://snippet-generator.app/ 示例文件: { "page快速模板":{ "prefix":"pg", "body":[ "Page({", " /**", " * 页面的初始数据", " */", " data: {\n ${1:Name}:${2:value},", " },", " /**", " * 用户点击右上角分享", " */", " onShareAppMessage(){", "", " },$0", "})" ], }, "当前时间打印内容":{ "prefix":"clg", "body":"console.log('$CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND:$1')" }, "v-for模板": { "prefix": ":vf", "body": ["wx:for='{{$1}}' wx:key='{{$2}}' bindtap='$3' data-$4='{{$5}}'"], "description": "v-for" }, "return false": { "prefix": "rf", "body": [ "return false;", ], "description": "函数无返回值时使用" }, "图片": { "prefix": "tp", "body": [ "<image src=\"{{${1}}}\" mode=\"${2|scaleToFill,aspectFit,widthFix,heightFix|}\"></image>" ], "description": "图片" } }
2022-08-22 - 2023年了,wx.compressVideo在ios手机上还是压缩失败吗?
wx.compressVideo苹果手机压缩视频不成功,安卓手机压缩很慢
2023-05-25 - gitlens 插件问题一直报错?
[图片] 版本:1.05.2201240
2022-02-15 - 如何彻底解决小程序滚动穿透问题
背景 俗话说,产品有三宝:弹窗、浮层加引导,足以见弹窗在产品同学心目中的地位。对任意一个刚入门的前端同学来说,实现一个模态框基本都可以达到信手拈来的地步,但是,当模态框里边的内容滚动起来以后,就会出现各种各样的让人摸不着头脑的问题,其中,最出名的想必就是滚动穿透。 什么是滚动穿透? 滚动穿透的定义:指我们滑动顶层的弹窗,但效果上却滑动了底层的内容。 具体解决方案分析如下: 改变顶层:从穿透的思路考虑,如果顶层不会穿透过去,那么问题就解决了,所以我们尝试给蒙层加catchtouchmove,但是发现部分场景无效果,那么就不再赘述了。 改变底层:既然是顶层影响了底层,要是底层不会滚动,那就没这个问题了。 如何改变底层解决该问题呢? 不成熟方案: 底部页面最外层view设置position: fixed;页面不可滚动,但是这个时候会导致页面回到顶部。 滚动时监听滚动距离,弹窗时记录滚动位置,关闭弹窗后使用wx.pageScrollTo回滚到记录的位置。 成熟方案 使用page-meta组件,通过该组件我们可以操作Page的style样式,类似于h5里body设置overflow: hidden; 控制页面不可滚动。文档地址:https://developers.weixin.qq.com/miniprogram/dev/component/page-meta.html 使用wx.setPageStyle设置overflow: hidden, 也可以实现给Page组件设置样式。) page-meta组件: 通过该组件我们可以直接操作[代码]Page[代码]组件 ,我们给它的wxss样式overflow动态设置[代码]hidden[代码]or[代码]visible[代码]or[代码]auto[代码] 就可以控制整个页面是否可以滚动。 [图片] wx.setPageStyle方法: 调用这个api,动态设置它为hidden/auto,用于控制页面是否可滚动,主要用于页面组件内使用,比如封装好的弹窗组件,就不用单独写page-meta组件了。。 [代码]wx.setPageStyle({ style: { overflow: 'hidden' // ‘auto’ } }) [代码] 老规矩,结尾放代码片段: https://developers.weixin.qq.com/s/U6ItgQmP7upQ 拓展 支付宝小程序虽然存在page-meta组件,但是由于内核为69版本,给page设置overflow: hidden 也无法控制底部元素不可滚动,目前已联系支付宝的底层开发同学提供API控制页面disableScroll,目前正在封装Appx,近期开放。
08-06 - 微信小程序wxss可以动态的用js的值吗?怎么传?
我想在wxss中设置js获取到的背景图片url,怎么把值传给wxss啊
2022-03-07 - [ app.json 文件内容错误] app.json: app.json 未找到?
[图片]
2021-01-06