- 多行文字溢出省略号IOS样式错误?
[图片] IOS做两行溢出文本的时候省略号与文字重叠,安卓和模拟器都正常,IOS真机异常 问题代码如下 <view class="test">测试测试测试测2033试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</view> .test { width: 300rpx; padding: 0 20rpx; display: -webkit-box; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; text-align: justify; white-space: normal; font-size: 28rpx; line-height: 35rpx; padding-top: 200rpx; } 另外代码片段真机预览的文字溢出省略号处理也有异常 代码片段webview渲染模式下text-overflow: ellipsis;在真机预览上完全失效,模拟器正常
2023-12-13 - image组件,页面加载时,图片有明显的从下往上的加载效果,像闪了一下
您好! 我这边做小程序开发,image组件的mode都用的是widthFix。。但是页面加载过程中,明显能看到图片自上而下的加载过程,就像是闪了一下。。用户体验不是很好,网上也搜过,没发现类似的问题。 知道是什么原因吗?求解答,多谢!
2018-05-10 - 社区每周|Android 系统蓝牙权限适配指引及上周问题反馈(07.29-08.02)
各位微信开发者: 以下是Android 系统蓝牙权限适配指引、小程序基础库 3.5.3 更新以及上周我们在社区收到的问题反馈的处理进度,希望与大家一同打造更好的小程序生态! Android 系统蓝牙权限适配指引 为响应Android 14对于蓝牙权限的变更,微信 自 8.0.50 版本起调用蓝牙相关接口时将向用户请求 “附近设备” 的系统权限。若用户拒绝此权限,小程序将无法调用蓝牙相关接口。 开发者可通过 wx.getAppAuthorizeSetting 接口中的 bluetoothAuthorized 参数判断微信的权限状态。若用户拒绝此权限,可通过 wx.openAppAuthorizeSetting 接口打开微信设置页引导用户打开权限 小程序基础库 3.5.3 更新 小程序基础库 3.5.3 已经开始灰度开发者,请大家基于业务情况关注相关变更。如遇问题请及时在小程序交流专区发表标题包含「基础库 3.5.3」的帖子反馈。本次更新重点如下: 新增 API 小游戏新增 wx.offShareMessageToFriend 详情更新 框架 小游戏真正用到开放数据域再禁用主屏 readPixels更新 框架 安卓 downloadFile 、uploadFile 接口性能优化更多更新内容请查看 原公告 上周问题反馈与处理进度(07.29-08.02) 已修复的问题wx.openLocation顶部导航栏显示的问题 详情 修复中的问题PC端小程序发送的请求全部失败的问题 详情 小程序API wx.getAppAuthorizeSetting() 返回值异常 详情 微信团队 2024年8月9日
08-09 - openBluetoothAdapter华为鸿蒙系统手机接口报错蓝牙功能无法使用
wx.openBluetoothAdapter 华为鸿蒙系统手机报错信息system permission denied,这两天出现很多用户反馈 [图片][图片]
07-08 - 常见小程序优化方案总结
一、首次启动性能优化 1、首次打开一个小程序,用户一般会观察到如下图所示的三种状态 [图片] 这张图中的三种状态对应的都是什么呢?小程序启动时,微信会为小程序展示一个固定的启动界面,界面内包含小程序的图标、名称和加载提示图标。 此时,微信会在背后完成几项工作:下载小程序代码包、加载小程序代码包、初始化小程序首页。下载到的小程序代码包不是小程序的源代码,而是编译、压缩、打包之后的代码包。 2、小程序加载的顺序 微信会在小程序启动前为小程序准备好通用的运行环境。这个运行环境包括几个供小程序使用的线程,并在其中完成小程序基础库的初始化,预先执行通用逻辑,尽可能做好小程序的启动准备。这样可以显著减少小程序的启动时间。 [图片] 通过这张图可以对比发现,小程序首次启动的 第一张图是资源准备(代码包下载);第二张图是业务代码的注入以及落地页首次渲染;第三张图是落地页数据请求时的loading态(部分小程序存在)。 3、优化方案 控制包大小:上传代码时要先进行压缩、静态图片资源除小的icon外其余放到cdn、无用代码清除; 分包加载:根据业务场景,将用户访问率高的页面放在主包里,将访问率低的页面放入子包里,按需加载; 分包预加载:在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。对于独立分包,也可以预下载主包。分包预下载 官方文档链接 独立分包技术:区别于子包,和主包之间是无关的,在功能比较独立的子包里,使用户只需下载分包资源;独立分包 官方文档链接 二、渲染性能优化 1、数据渲染优化 双线程下的界面渲染,小程序的逻辑层和渲染层是分开的两个线程。在渲染层,宿主环境会把WXML转化成对应的JS对象,在逻辑层发生数据变更的时候,我们需要通过宿主环境提供的setData方法把数据从逻辑层传递到渲染层,再经过对比前后差异,把差异应用在原来的Dom树上,渲染出正确的UI界面。 [图片] 页面初始化的时间大致由页面初始数据通信时间和初始渲染时间两部分构成。其中,数据通信的时间指数据从逻辑层开始组织数据到视图层完全接收完毕的时间,数据量小于64KB时总时长可以控制在30ms内。传输时间与数据量大体上呈现正相关关系,传输过大的数据将使这一时间显著增加。因而减少传输数据量是降低数据传输时间的有效方式。 [图片] 在数据传输时,逻辑层会执行一次JSON.stringify来去除掉setData数据中不可传输的部分,之后将数据发送给视图层。同时,逻辑层还会将setData所设置的数据字段与data合并,使开发者可以用this.data读取到变更后的数据。因此,为了提升数据更新的性能,可以参考如下方法: 1.不要过于频繁调用setData,应考虑将多次setData合并成一次setData调用; 2.数据通信的性能与数据量正相关,因而如果有一些数据字段不在界面中展示且数据结构比较复杂或包含长字符串,则不应使用setData来设置这些数据; 3.与界面渲染无关的数据最好不要设置在data中,可以考虑设置在page对象的其他字段下; 4.勿在后台页面去setData; 5.建议创建一个检测data大小的方法,如果超过64K可以打印报警日志提醒开发者; 2、长列表优化方案 无限下拉加载后会大数据量展现导致的性能问题,一个常见的方法在诸多C端都有使用,一句话说就是"只渲染所需的元素"。虚拟列表是按需显示思路的一种实现,即虚拟列表是一种根据滚动容器元素的可视区域来渲染长列表数据中某一个部分数据的技术。简而言之,虚拟列表指的就是「可视区域渲染」的列表。有三个概念需要了解一下: 滚动容器元素:一般情况下,滚动容器元素是 window 对象。然而,我们可以通过布局的方式,在某个页面中任意指定一个或者多个滚动容器元素。只要某个元素能在内部产生横向或者纵向的滚动,那这个元素就是滚动容器元素考虑每个列表项只是渲染一些纯文本。在本文中,只讨论元素的纵向滚动。 可滚动区域:滚动容器元素的内部内容区域。假设有 100 条数据,每个列表项的高度是 50,那么可滚动的区域的高度就是 100 * 50。可滚动区域当前的具体高度值一般可以通过(滚动容器)元素的 scrollHeight 属性获取。用户可以通过滚动来改变列表在可视区域的显示部分。 可视区域:滚动容器元素的视觉可见区域。如果容器元素是 window 对象,可视区域就是浏览器的视口大小(即视觉视口);如果容器元素是某个 div 元素,其高度是 300,右侧有纵向滚动条可以滚动,那么视觉可见的区域就是可视区域。 实现虚拟列表就是在处理用户滚动时,要改变列表在可视区域的渲染部分,其具体步骤如下: 计算当前可见区域起始数据的 startIndex 计算当前可见区域结束数据的 endIndex 计算当前可见区域的数据,并渲染到页面中 计算 startIndex 对应的数据在整个列表中的偏移位置 startOffset,并设置到列表上 计算 endIndex 对应的数据相对于可滚动区域最底部的偏移位置 endOffset,并设置到列表上 [图片] 虚拟列表的实现原理可以参考这篇文章:浅说虚拟列表的实现原理 3、长列表局部渲染技巧 在一个列表中,有n条数据,采用上拉加载更多的方式。假如这个时候想对其中某一个数据进行点赞操作,还能及时看到点赞的效果,可以采用setData全局刷新,点赞完成之后,重新获取数据,再次进行全局重新渲染,这样做的优点是:方便,快捷!缺点是:用户体验极其不好,当用户刷量100多条数据后,重新渲染量大会出现空白期(没有渲染过来)。 优化步骤: 1.将点赞的[代码]id[代码]传过去,知道点的是那一条数据, 将点赞的[代码]id[代码]传过去,知道点的是那一条数据 <view wx:if="{{!item.status}}" class=“btn” data-id="{{index}}" bindtap=“couponTap”>立即领取</view> 2.重新获取数据,查找相对应id的那条数据的下标([代码]index[代码]是不会改变的) 3.用setData进行局部刷新 this.setData({ list[index] : newList[index] }) 4、用户事件优化 视图层将事件反馈给逻辑层时,同样需要一个通信过程,通信的方向是从视图层到逻辑层。因为这个通信过程是异步的,会产生一定的延迟,延迟时间同样与传输的数据量正相关,数据量小于64KB时在30ms内。降低延迟时间的方法主要有两个。 1.去掉不必要的事件绑定(WXML中的bind和catch),从而减少通信的数据量和次数; 2.事件绑定时需要传输target和currentTarget的dataset,因而不要在节点的data前缀属性中放置过大的数据。 三、生命周期优化 1、异步请求,页面渲染需要的数据最好在onLoad时异步请求数据,不要在onReady时请求;非页面渲染需要的数据,尽量放在onReady生命周期去调用; 2、定时器、事件监听、播放组件、音视频组件等,在页面转入后台(onHide)或者销毁(onUnload)时应该中止掉; 四、图片静态资源预加载 在日常小程序的开发中,有很多的大图片是放置于cdn上的,在需要进行展示的时候,如果没有预加载有可能出现图片展示的不及时,造成不好的体验,所以如下方式实现了图片预加载的功能,可以封装成组件的形式。 实现思路是将图片添加进页面中,设置不可见,然后加载图片,实现一个预加载的功能。 1、添加模版文件: img-loader.wxml <template name=“img-loader”> <image mode=“aspectFill” wx:for="{{ imgLoadList }}" wx:key="*this" src="{{ item }}" data-src="{{ item }}" bindload="_imgOnLoad" binderror="_imgOnLoadError" style=“width:0;height:0;opacity:0” /> </template> 2、添加js文件:img-loader.js /** 图片预加载组件 */ class ImgLoader { /** 初始化方法,在页面的 onLoad 方法中调用,传入 Page 对象及图片加载完成的默认回调 */ constructor(pageContext, defaultCallback) { this.page = pageContext this.defaultCallback = defaultCallback || function () { } this.callbacks = {} this.imgInfo = {} [代码]this.page.data.imgLoadList = [] //下载队列 this.page._imgOnLoad = this._imgOnLoad.bind(this) this.page._imgOnLoadError = this._imgOnLoadError.bind(this) [代码] } /** 加载图片 @param {String} src 图片地址 @param {Function} callback 加载完成后的回调(可选),第一个参数个错误信息,第二个为图片信息 */ load(src, callback) { if (!src) return; [代码]let list = this.page.data.imgLoadList, imgInfo = this.imgInfo[src] if (callback) this.callbacks[src] = callback //已经加载成功过的,直接回调 if (imgInfo) { this._runCallback(null, { src: src, width: imgInfo.width, height: imgInfo.height }) //新的未在下载队列中的 } else if (list.indexOf(src) == -1) { list.push(src) this.page.setData({ 'imgLoadList': list }) } [代码] } _imgOnLoad(ev) { let src = ev.currentTarget.dataset.src, width = ev.detail.width, height = ev.detail.height [代码]//记录已下载图片的尺寸信息 this.imgInfo[src] = { width, height } this._removeFromLoadList(src) this._runCallback(null, { src, width, height }) [代码] } _imgOnLoadError(ev) { let src = ev.currentTarget.dataset.src this._removeFromLoadList(src) this._runCallback(‘Loading failed’, { src }) } //将图片从下载队列中移除 _removeFromLoadList(src) { let list = this.page.data.imgLoadList list.splice(list.indexOf(src), 1) this.page.setData({ ‘imgLoadList’: list }) } //执行回调 _runCallback(err, data) { let callback = this.callbacks[data.src] || this.defaultCallback callback(err, data) delete this.callbacks[data.src] } } module.exports = ImgLoader 3、在需要使用预加载功能的xxx.wxml页面中加入模版文件和使用代码: <import src="…/…/templates/img-loader.wxml"/> <template is=“img-loader” data="{{ imgLoadList }}"></template> 4、在需要使用预加载功能页面的xxx.js文件中引入文件和使用代码: import ImgLoader from ‘…/…/templates/img-loader.js’; let images = [ ‘http://cdn.weimob.com/saas/activity/bargain/images/arms/shoulie.png’, ‘http://cdn.weimob.com/saas/activity/bargain/images/arms/shandian.png’, ‘http://cdn.weimob.com/saas/activity/bargain/images/arms/fengbao.png’ ] //初始化图片预加载组件,并指定统一的加载完成回调 this.imgLoader = new ImgLoader(this, this.imageOnLoad.bind(this)); images.forEach(item => { this.imgLoader.load(item) }) 备注:如有错误请帮忙指出;如有侵权,请联系我们删除,谢谢!
2019-09-03 - downloadTask.abort()如何正常使用,高版本又失效?
我有一个B页面,需要多次使用,在A页面点击按钮会进入B页面,B页面点击返回会返回A页面 A页面点击进入B页面时候,B页面开始下载文件,并且显示,有时候,使用者在B页面还没下载完成时候,就返回,然而,下载进程仍在继续,多次重复进入B页面的时候,可能会导致小程序崩溃。 因此希望在B页面返回A页面的时候,如果发现B页面数据没下载完成,就使用downloadtask.abort()来终止该任务 但是每次都报错出现downloadfile:fail abort 当前版本小程序开发工具 V1.02.1907300 调试基础库 2.8.3 测试手机IOS 8plus 系统 ios 13.1.2 希望修复这个问题,由于本人使用了three.js等,所以不可能说调低库的版本 [图片]
2019-10-15 - tab跳转后 上一个页面的网络请求还在执行
tab跳转后 上一个页面的网络请求还在执行 请求完成后回调也会执行。 比如我在上一个列表 获取了 订单列表。在这个请求完成之前我跳转了页面,然后请求完成,在新的页面弹出 请求完成的提示信息。 这个如何解决啊。。。接口太多的话 难道每个都要 RequestTask.abort()吗。。。而且网络请求还封装过
2018-11-06 - requestTask.abort()失效
requestTask.abort()失效 loadData(){ const task = wx.request({ url: 'http://192.168.31.127', success:res=>{ console.log(res); }, fail:err=>{ console.log(err); } }); task.abort(); }, onLoad: function (options) { this.loadData(); },
2018-12-01 - 解读微信内网页跳转到APP方法,使用微信开放标签:<wx-open-launch-app>
1、功能说明 微信内置浏览器支持的<wx-open-launch-app>开放标签可以让你的H5网页拉起APP。这个是不是很神奇也是很有必要的一个功能?微信为你想好啦~实现这个功能并不复杂,代码量可以忽略为0.但是一些相关的注意事项,准入规则还是必须要明确的,否则在开发过程中容易踩到各种坑。 2、接入逻辑 2.1 设置服务号的JS安全域名,开放标签必须在这个域名或者子域名下生效详见《微信开放标签说明文档》 2.2 注册登陆微信开放平台,新建APP审核并上架成功。然后登记域名和你的APP应用绑定关系,让他们能关联起来 [图片] 3、准入门槛 看起来第二大步很简单,其实操作起来还是有点繁琐的,除去繁琐的设置外,这里有个准入门槛: 3.1 服务号门槛 服务号已认证 开放平台账号已认证 服务号与开放平台账号同主体 绑定域名和移动应用 绑定域名的要求: 域名须为当前服务号的 JS 安全域名或其子域名 域名只能同时绑定一个移动应用,因此须确保域名未被其他移动应用绑定 3.2 绑定移动应用的要求 只能绑定同一微信开放平台账号下审核通过的移动应用 3.3 绑定次数 每月可修改绑定3次 4、参考文档: 微信内网页跳转APP功能-功能介绍 | 微信开放文档 开放标签说明文档 | 微信开放文档
2020-05-07 - 有办法确认手机连接的WiFi频率是单独5G还是2.4G和5G双频的吗?
程序需要知道连接的WiFi是5G还是5G/2.4G双频的呀,现在的获得的频率不管是5G还是2.4G/5G双频都是显示5G频率的,有什么方法可以知道吗?
2021-03-12 - Editor组件怎么插入视频?
Editor组件怎么插入视频?现在只看到了插入图片。
2023-07-13 - 小程序editor,插入带有text-indent样式的文本会自动插入空格
editorCtx.setContents({ html: `<p style="text-indent:2em">插入的富文本内容</p>` }) getContents得到结果为: html:<p style="text-indent: 2em;"> 插入的富文本内容</p> text: 插入的富文本内容↵ 表现为编辑器内多出一个空格; [图片]
2022-06-08 - wx.onGetWifiList在ios中不进入回调
这里需要注意: 1、Wi-Fi 相关接口的调用时序,参考:https://developers.weixin.qq.com/miniprogram/dev/framework/device/wifi.html 2、需要跳转到系统 WiFi 列表,等到列表刷新出 WiFi,在微信前台的小程序才会收到 onGetWifiList 的回调;这是苹果系统的限制,暂时无法规避
2019-09-24 - wx.getConnectedWifi连接wifi wifiInfo里面没得frequency字段?
苹果获取手机wifi信息 里面有SSID,BSSID signalStrength,但是就没得frequency
2022-12-01 - 为什么我连接上双频wifi,使用getConnectedWifi接口不返回两个wifiinfo?
设备需要支持双频wifi
2023-12-21 - 长图中带了小程序码,安卓机长按识别不了
在微信聊天对话框中发送该图片,安卓长按识别不到小程序码(ios可以) [图片]
2023-01-31 - 微信小程序开发工具中用苹果手机扫描小程序二维码预览正常,用安卓手机扫描二维码进不去怎么回事?
在微信小程序开发工具中,点击预览或真机调试生成二维码,用苹果手机扫描二维码可以正常打开,用安卓手机扫描二维码打不开
2020-10-10 - 关于微信扫码识别问题
微信扫一扫存在的问题: 目前我们在小程序调用扫一扫识别密度很高的QR码,普通的手机很难识别出来结果,但iphone会好一些,这里部是说iphone好,识别二维码有很多综合因素,角度 亮度 清晰度 分辨率 手机相机等问题存在,但是二维码解码的算法 微信是存在问题的,我用相同的二维码用微信扫很散识别 用支付宝就人容易,而且我用了几个手机都是一样 支付宝的扫一扫就很好用, 我只是想说希望等对微信扫一扫算法进行优化,至少不能比支付宝差吧
2018-09-21 - 小程序实现列表拖拽排序
小程序列表拖拽排序 [图片] wxml [代码]<view class='listbox'> <view class='list kelong' hidden='{{!showkelong}}' style='top:{{kelong.top}}px'> <view class='index'>?</view> <image src='{{kelong.xt}}' class='xt'></image> <view class='info'> <view class="name">{{kelong.name}}</view> <view class='sub-name'>{{kelong.subname}}</view> </view> <image src='/images/sl_36.png' class='more'></image> </view> <view class='list' wx:for="{{optionList}}" wx:key=""> <view class='index'>{{index+1}}</view> <image src='{{item.xt}}' class='xt'></image> <view class='info'> <view class="name">{{item.name}}</view> <view class='sub-name'>{{item.subname}}</view> </view> <image src='/images/sl_36.png' class='more'></image> <view class='moreiconpl' data-index='{{index}}' catchtouchstart='dragStart' catchtouchmove='dragMove' catchtouchend='dragEnd'></view> </view> </view> [代码] wxss [代码].map-list .list { position: relative; height: 120rpx; } .map-list .list::after { content: ''; width: 660rpx; height: 2rpx; background-color: #eee; position: absolute; right: 0; bottom: 0; } .map-list .list .xt { display: block; width: 95rpx; height: 77rpx; position: absolute; left: 93rpx; top: 20rpx; } .map-list .list .more { display: block; width: 48rpx; height: 38rpx; position: absolute; right: 30rpx; top: 40rpx; } .map-list .list .info { display: block; width: 380rpx; height: 80rpx; position: absolute; left: 220rpx; top: 20rpx; font-size: 30rpx; } .map-list .list .info .sub-name { font-size: 28rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #646567; } .map-list .list .index { color: #e4463b; font-size: 32rpx; font-weight: bold; position: absolute; left: 35rpx; top: 40rpx; } [代码] js [代码]data:{ kelong: { top: 0, xt: '', name: '', subname: '' }, replace: { xt: '', name: '', subname: '' }, }, dragStart: function(e) { var that = this var kelong = that.data.kelong var i = e.currentTarget.dataset.index kelong.xt = this.data.optionList[i].xt kelong.name = this.data.optionList[i].name kelong.subname = this.data.optionList[i].subname var query = wx.createSelectorQuery(); //选择id query.select('.listbox').boundingClientRect(function(rect) { // console.log(rect.top) kelong.top = e.changedTouches[0].clientY - rect.top - 30 that.setData({ kelong: kelong, showkelong: true }) }).exec(); }, dragMove: function(e) { var that = this var i = e.currentTarget.dataset.index var query = wx.createSelectorQuery(); var kelong = that.data.kelong var listnum = that.data.optionList.length var optionList = that.data.optionList query.select('.listbox').boundingClientRect(function(rect) { kelong.top = e.changedTouches[0].clientY - rect.top - 30 if(kelong.top < -60) { kelong.top = -60 } else if (kelong.top > rect.height) { kelong.top = rect.height - 60 } that.setData({ kelong: kelong, }) }).exec(); }, dragEnd: function(e) { var that = this var i = e.currentTarget.dataset.index var query = wx.createSelectorQuery(); var kelong = that.data.kelong var listnum = that.data.optionList.length var optionList = that.data.optionList query.select('.listbox').boundingClientRect(function (rect) { kelong.top = e.changedTouches[0].clientY - rect.top - 30 if(kelong.top<-20){ wx.showModal({ title: '删除提示', content: '确定要删除此条记录?', confirmColor:'#e4463b' }) } var target = parseInt(kelong.top / 60) var replace = that.data.replace if (target >= 0) { replace.xt = optionList[target].xt replace.name = optionList[target].name replace.subname = optionList[target].subname optionList[target].xt = optionList[i].xt optionList[target].name = optionList[i].name optionList[target].subname = optionList[i].subname optionList[i].xt = replace.xt optionList[i].name = replace.name optionList[i].subname = replace.subname } that.setData({ optionList: optionList, showkelong:false }) }).exec(); }, [代码]
2019-07-28 - 小程序实现的列表上下拖拽排序
先来看看效果 快速拖拽排序测试演示视频地址:https://v.qq.com/x/page/r3207k4fxe1.html 完整拖拽排序效果演示视频地址:https://v.qq.com/x/page/y3207g6agur.html [图片] 采用技术:uni-app 接下来分析分析实现该效果所需要用到的标签 元素是通过拖拽进行排序的,此处采用的是官方出的 <movable-area> <movable-view> 两位标签大佬解决移动的问题 (主要是相信官方支持的动画会比自己搞更加丝滑一些)。支持拖拽到上下边界,检查可视区域的位置并自动进行滚动, 此处就需要我们的 <scroll-view> 标签大佬坐镇了。标签的选择搞定了,再来了解了解这些标签要用到的重点属性 movable-view 想要移动就必须作为 movable-area 的直接子元素,且 movable-area 必须设置 width,height 属性 (还有些提示可以查看文档)。movable-view 的 x, y 属性决定了 movable-view 再 movable-area 所处的位置 (是不是猜出了要搞些什么东东了)scroll-view 滚动到指定位置可以通过控制 scroll-top 的属性值来进行控制滚动 接下来就是怎么个实现思路,先来捋捋实现的步骤 列表该如何渲染如何控制拖拽元素的跟随如何使拖拽中的元素与相交互的元素进行位置调换如何判断拖拽元素至上下边界滚动屏幕如何使页面的滚动与拖拽时的滚动互不影响 描述完宏观的蓝图,接下来就是代码小细节,客官请随我来 一、解决列表渲染问题 /** * 上面说到 movable-view 可以通过 x,y 决定它的位置, 且 movable-area 需要设置 widht,height 属性 * 配置完这些属性 movable-view 就可以再 movable-area 愉快的拖拽玩耍了 * 思路: * 1. 通过列表的数量乘于显示列表项的高度得出最终可拖拽区域的总高度,赋值给 movable-area * 2. 扩展列表项一些字段,此处使用 y 保存当前项距离顶部位置, idx 保存当前项所在列表的下标 / // 伪代码 // js initList(list) { this.areaHeight = list.length * this.height; // aeraHieght 可拖拽区域总高度, height 为元素所需高度 this.internalList = list.map((item, idx) => { return { ...item, y: idx * this.height, // movable-view 当前项所处的高度 idx: idx, // 当前项所处于列表的下标,用于比较 animation: true, // 主要用于控制拖拽的元素要关闭动画, 其他的元素可以保留动画 } }) } // html 二、 如何控制拖拽元素的跟随 // 主要是通过监听 movable-view 的 touchstart touchmove touchend 三个事件完成拖拽动作的起始、移动、结束。 // methods { _dragStart(e){ // 取得触摸点距离行顶部距离 this.deviationY = (e.mp.touches[0].clientY - this.wrap.top) % this.height; this.internalList[idx].animation = false; // 关闭当前拖拽元素的动画属性 this.activeIdx = idx; // 保存当前拖拽元素的下标 }, _dragMove(e) { const activeItem = this.internalList[this.activeIdx]; if (!activeItem) return; // 实时取得触摸点的位置信息 const clientY = e.mp.touches[0].clientY; let touchY = clientY - this.wrap.top - this.deviationY + this.scrollTop; if (touchY <= 0 || touchY + this.height >= this.areaHeight) return; activeItem.y = touchY; // 拖拽元素的移动秘密就在于此 } } 三、如何使拖拽中的元素与相交互的元素进行位置调换 // 上述代码解决了当前拖拽元素的位置移动问题, 接下来就需要解决拖拽元素和上下元素交互的问题 // methods { __dragMove(e){ // ...同上代码一致 // 上下元素交互位置代码实现 for(let item of this.internalList) { if (item.idx !== activeItem.idx) { if (item.idx > activeItem.idx) { // 如果当前元素下标大于拖拽元素下标,则检查当前拖拽位置是否大于当前元素中心点 if (touchY > item.idx * this.height - this.height / 2) { [activeItem.idx, item.idx] = [item.idx, activeItem.idx]; // 对调位置 item.y = item.idx * this.height; // 更新对调后的位置 break; // 退出循环 } } else { // 如果当前元素下标小于拖拽元素下标,则检查当前拖拽位置是否小于当前元素中心点 if (touchY < item.idx * this.height + this.height / 2) { [activeItem.idx, item.idx] = [item.idx, activeItem.idx]; item.y = item.idx * this.height; break; } } } } } } 四、如何判断拖拽元素至上下边界滚动屏幕 // 将 movable-area 包裹在 scroll-view 标签中, 通过控制 scroll-top 的值来进行滚动 // 思路: 判断当前拖拽元素的位置信息与当前屏幕可视区域进行比较 // methods { _dragMove(e) { // ...同上代码 // 检查当前位置是否处于可视区域 if (activeItem.idx + 1 * this.height + this.height / 2 > this.scrollTop + this.wrap.top) { this.viewTop = this.scrollTop + this.height; // 往上滚动一个元素的高度 } else if (activeItem.idx * this.height - this.height / 2 < this.scrollTop ) { this.viewTop = this.scrollTop - this.height; // 往下滚动一个元素的高度 } } } 五、如何使页面的滚动与拖拽时的滚动互不影响 // 事实上我是通过一种取巧的方式, scroll-veiw 有一个 scroll-y 属性可以控制滚动方向 // 思路: // 1.不进行滚动的时候将 scroll-y 置为 true , 使用默认的滚动效果 // 2.当进入拖拽排序状态时则将 scroll0y 置为 false, 滚动通过拖拽代码比较计算滚动位置 完整代码: 主要小程序上的插槽不允许往外传值、所以自定义元素实现的方式相比于H5实现Vue的方式比较别扭。 因为有多个地方需要用到排序功能,所以边抽离了 js 部分进行混入。 // DargSortMixin.js 文件 export default { props: { list: { type: Array, default() { return []; }, }, sort: { type: Boolean, default: false, }, height: { type: Number, default: 66, }, }, data() { return { areaHeight: 0, // 区域总高度 internalList: [], // 列表 activeIdx: -1, // 移动中激活项 deviationY: 0, // 偏移量 // 包裹容器信息 wrap: { top: 0, height: 0, }, viewTop: 0, // 指定滚动高度 scrollTop: 0, // 容器实时滚动高度 scrollWithAnimation: false, canScroll: true, }; }, created() { // 组件使用选择器,需用使用this const query = this.createSelectorQuery(); query .select('#scroll-wrap') .boundingClientRect(rect => { if (rect) { this.wrap = { top: rect.top, height: rect.height, }; } }) .exec(); }, watch: { list: { handler(val) { this.initList(val); }, immediate: true, }, }, methods: { getList() { return this.internalList .sort((a, b) => { return a.idx - b.idx; }) .map(item => { let newItem = { ...item }; delete newItem.y; delete newItem.idx; delete newItem.animation; return newItem; }); }, initList(list) { this.areaHeight = list.length * this.height; this.internalList = list.map((item, idx) => { return { ...item, y: idx * this.height, idx, animation: true, }; }); }, _dragStart(e, idx) { // 取得触摸点距离行顶部距离 this.deviationY = (e.mp.touches[0].clientY - this.wrap.top) % this.height; this.internalList[idx].animation = false; // 关闭动画 this.activeIdx = idx; this.scrollWithAnimation = true; this.canScroll = false; }, _dragMove(e) { const activeItem = this.internalList[this.activeIdx]; if (!activeItem) return; // 保存触摸点位置和长按时中心一致 const clientY = e.mp.touches[0].clientY; let touchY = clientY - this.wrap.top - this.deviationY + this.scrollTop; if (touchY <= 0 || touchY + this.height >= this.areaHeight) return; activeItem.y = touchY; // 设置位置 // 检查元素和上下交互元素的位置 for (const item of this.internalList) { if (item.idx !== activeItem.idx) { if (item.idx > activeItem.idx) { if (touchY > item.idx * this.height - this.height / 2) { [activeItem.idx, item.idx] = [item.idx, activeItem.idx]; // 对调位置 item.y = item.idx * this.height; // 更新位置 break; } } else { if (touchY < item.idx * this.height + this.height / 2) { [activeItem.idx, item.idx] = [item.idx, activeItem.idx]; // 对调位置 item.y = item.idx * this.height; // 更新位置 break; } } } } // 检查当前位置是否处于可视区域 if ( (activeItem.idx + 1) * this.height + this.height / 2 > this.scrollTop + this.wrap.height ) { this.canScroll = true; activeItem.y = activeItem.idx * this.height; this.$nextTick(() => { this.viewTop = this.scrollTop + this.height; }); } else if (activeItem.idx * this.height - this.height / 2 < this.scrollTop) { this.canScroll = true; activeItem.y = activeItem.idx * this.height; this.$nextTick(() => { this.viewTop = this.scrollTop - this.height; }); } }, _dragEnd(e) { const activeItem = this.internalList[this.activeIdx]; if (!activeItem) return; activeItem.animation = true; activeItem.disabled = true; activeItem.y = activeItem.idx * this.height; this.activeIdx = -1; this.scrollWithAnimation = false; this.canScroll = true; }, _onScroll(e) { this.scrollTop = e.detail.scrollTop; }, }, }; // TheDragSortAreaList.vue 文件 import DragSortMixin from '@/mixins/DragSortMixin'; export default { name: 'TheDragSortTableList', mixins: [DragSortMixin], }; .active-item { z-index: 10; } .drag-item { background: $theme-color; color: $white !important; .count { color: $white !important; } }
2020-11-27 - scroll-view的refresher-triggered突然失效,设置false无法回弹?
目前确认,iOS端scroll-view的refresher-triggered突然失效,线上和开发环境在下拉刷新后设置refresher-triggered={{false}},无法将其恢复至原始未下拉状态,请官方予以查看并解决,谢谢。
06-08 - scroll-view自定义下拉刷新多次下拉刷新之后不能复位?
scroll-view 组件 在ios机型下, 频繁多次的操作下拉刷新 内容无法复位;微信版本号:8.0.49; 基础库:3.4以上都试过; <scroll-view class="scrollarea" scroll-y type="list" refresher-enabled="{{true}}" refresher-background="red" refresher-triggered="{{isRefresher}}" bindrefresherrefresh="onRefresh" > <view class="container"> <view class="userinfo"> XXXX </view> <view class="usermotto"> <text class="user-motto">{{motto}}</text> </view> </view> </scroll-view> js: onRefresh(event){ this.setData({ isRefresher:true }) setTimeout(()=>{ this.setData({ isRefresher:false }) }, 500) },
05-24 - 华为荣耀10
- 当前 Bug 的表现(可附上截图) 在当前页点击tab没有触发onTabItemTap事件 - 预期表现 在当前页点击tab触发onTabItemTap事件
2018-08-22 - scroll-view运行scroll-top无效
问题描述: scroll-view下两个tab,现想点击不同的tab, 重置scroll-top 为 0, 发现并没有真的置零。 重现步骤: 1,在“最新”tab下翻几屏查看 2,点击“最热” tab , 发现scrolltop仍然是前面 "最新"的scrolltop, 设置 scroll-top:0无效 界面如下: [图片] wxml如下: [图片] js如下: [图片]
2016-11-25 - image组件网络图片不显示,wx.previewImage可以显示?
1.目前是image触发了error事件,错误提示是图片404,实际上不是404; 2.wx.previewImage预览却可以显示出来,外部访问也可以,就是image组件无法显示。 3.不是所有机型如此,而是部分机型如此。目前不知道解决办法。 图片链接: https://api.new.dafang24.com:442/Attach/Upload/CheckCar/2024_04_01_11_30_45_34776864295194813197713408.jpg?token=o1MZPpRS4%2F8jzMD1vh7i8RmJ%2FG8kJXgkQD4NG5OyMEWkmNnPPhxyLQ%3D%3D&v=18917822990579114
04-01 - 小程序image组件有的时候会无法显示网络图片
image组件的src是网络图片,就是微信头像的链接,但是有的时候可以显示,有的时候就不能显示。 我把src同步输出在页面上,确保链接是正确的,但image就是不显示,不知道怎么回事,求教~
2017-11-27 - 浏览器图片可以访问 小程序image 图片无法显示?
https://scnj.hbck.com.cn/run/website/images/index/book.png 域名已经添加到服务器域名和业务域名中,但是图片依然无法显示出来,浏览器却可以正常访问,麻烦请教下!这个问题我搞了一下午了,还是不行,不知道是什么原因
2020-05-12 - 当屏幕滑到底部的时候 不松开屏幕 scroll-top 值设置为0了...
当屏幕滑到底部的时候 不松开屏幕 停顿个几秒后 scroll-top 值设置为0了 但屏幕并没有滑动到顶部 这种问题怎么解决? 所有手机都如此,去改变用户行为不大可能,因为我自己都习惯这么滑动 [图片] [图片] [图片][图片]
2019-07-29 - editor 组件获取焦点推起时候页面不会上推 怎么解决?
editor 组件获取焦点推起时候页面不会上推(是部分机型不会例如华为) 并且editor 组件也没有adjust-position设置 没有办法自己去设置上推界面
2023-12-25 - wx.chooseImage勾选原图时,文件大小提示不对?
现象:勾选原图时,显示为2M;实际图片下载下来后,为7.6M。有个需求要限制图片大小,超过固定大小后禁止上传,测试同学还给提了个bug,明明这里显示的2M,小于后台设置的阈值3M,问为啥上传不了。通过调试发现,确实tempFiles中size返回的是通过计算后为7.6M。如下图所示: [图片][图片]
2022-04-28 - IOS wx.chooseImage 返回的size值比原图片大很多?
苹果手机端使用wx.chooseImage选择原图片上传时,部分图片的成功回调函数返回的图片size值比相册中查看的图片大小会大很多,比如相册中查看图片大小是15MB,但是wx.chooseImage返回的size值却是30MB,请问这种情况怎么解决呢?
2022-09-07 - 微信小程序chooseImage的size问题
调用chooseimg接口,返回的size与实际图片大小不一致,图片在电脑中的大小为10.2Mb,手机中为9.9Mb,通过接口获取(已选择原图)的大小为4Mb左右
2019-03-28 - editor组件每次点击可输入文本区域都会重新拉键盘?
editor每次点击可输入文本区域都会重新拉起键盘一次,不像input等输入框一样,这个是组件bug吗?
2022-05-07 - 部分EMOJI无法在text和rich-text组件显示
手机端(IOS未测试)text和rich-text组件均无法显示部分EMOJI,但通过canvas绘制EMOJI字符或开发者工具上均能正确显示。 刚刚又测试了下textarea和input的支持情况,textarea在有无焦点情况下都能正确显示,而input在无焦点下不能显示,有焦点时可以显示 (代码片段已提供一键复制测试的EMOJI字符,可直接粘贴到textarea和input进行测试) 开发者工具:text组件和canvas绘图均能正确显示 [图片] 手机端(安卓):text组件无法显示,canvas绘图能正确显示 [图片] textarea:无论有无焦点均能显示 [图片] input:无焦点下不能显示,有焦点时可以显示 [图片]
2019-11-28 - 小程序editor富文本编辑器长按显示系统复制粘贴,抬手时失去焦点导致复制粘贴弹窗不显示bug?
editor组件地址:https://developers.weixin.qq.com/miniprogram/dev/component/editor.html#%E5%B1%9E%E6%80%A7%E8%AF%B4%E6%98%8E 组件名称:editor 富文本编辑器 微信版本号:8.0.38 基础库版本号:2.30.2bug复现步骤:1.长按显示系统复制粘贴, 2.抬手时自动失去焦点,键盘收起,复制、全选粘贴弹窗自动隐藏了,不显示bug。
2023-07-14 - editor的 insertImage API,插入图片后会多了个<p><br></p>?
富文本编辑器editor的 insertImage API,插入图片后会多了个<p><br></p> [代码]let that = [代码][代码]this[代码][代码];[代码][代码]this[代码][代码].editorCtx.insertImage({[代码][代码] src: [代码][代码]"https://www.hongbk.club/emotion/"[代码][代码]+[代码][代码]this[代码][代码].emotion[index].name+[代码][代码]".png"[代码][代码],[代码][代码] [代码][代码]extClass: [代码][代码]'emoji_img'[代码][代码],[代码][代码] [代码][代码]success() {[代码][代码] [代码][代码]that.editorCtx.getContents({ [代码][代码] [代码][代码]success(res) {[代码][代码] [代码][代码]console.log(res.html)[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}) [代码][代码] [代码][代码]}[代码][代码]})[代码] 打印的结果: [图片]
2019-11-06 - editor 可否添加获取、设定光标位置功能?
editor作为小程序功能丰富的表单组件,还是却不少能力。 因为textarea不好修改用户输入,editor如果添加获取、设定光标的能力,可以解决不少的应用场景,比如:输入框中可以@用户,小程序会替换相关的提醒代码。 目前每次使用editorContext.setContents(),光标会返回输入框首位,使用户体验非常不方便。而且,无法获取当前光标位置也使很多开发场景无法实现(比如说用户正在删除哪些文字,是否前面描述的提醒代码段等)。请团队考虑下,谢谢
2021-03-05 - editor组件光标层级太高,fixed盖不住
[图片] 工具是fixed定位的
2022-07-29 - editor组件在编辑时光标位置问题?
使用editor时,在我使用EditorContext.setContents({html:'编辑内容'})后,进行真机调试,当我第一次(只是第一次)点击内容时准备在任意字符后插入或追加文字时,光标总是停留在第一个字符前。有没有什么解决办法?
2020-02-19 - 小程序如何监听阻止左侧向右滑动返回上一页面?
现在有个需求左侧向右滑动返回上一页面我们先出现我们自己的一个弹框处理一些逻辑,可是现在不知道要如何阻止这个返回呢?
2023-05-08 - 在小程序内打开doc文件失败问题总结
本文背景今天我在优化党建答题助手小程序,具体优化的内容就是之前的活动规则页是通过小程序代码内写的,每次活动规则变动,都要通过发版本来处理,这无疑增加了我的工作量, 计划把这个改成通过富文本或者文件的形式,这两种方式都可以,本文是将活动规则通过文件形式,具体如下图所示 截图一 [图片] 截图二 [图片] 本文内容在具体改造的过程中,文件首先是保存成doc然后上传到云存储,后面发现不可行,具体的报错信息如下所示 [图片] 后面改成docx,问题得到解决 其实这个问题在社区有很多帖子有问到,但是doc这种文件类型在官方的文档中是明确支持的,不清楚为什么报不支持的文件类型 本文总结本文通过对小程序例行迭代过程中发现,小程序内打开doc文件失败,进而通过将文件类型改为docx,从而顺序完成本次的优化任务,如果有遇到类似问题的同学可以参考
2020-09-20 - 已发布的微信小程序在微信中搜索不到?
发布的微信小程序在微信中无法搜索,但扫码可以打开,微信公众平台未收到任何通知整改,账号原始ID:gh_cb6d2371b2ed 小程序AppID:wx7c5e10e30ad9b27b,小程序名称:驼分清运
2023-04-13 - 第二次进入页面后,setData 设置值无效
第一次进入页面,设置pushUrl , 和palyStream, 这两个值可以更新到视图, 退出这个页面,这次进入,设置了同样的值,发现 视图里没有更新。 第二次在函数里打印this: [图片] 在开发者工具里看 appData: 里面的数据是空的 [图片] 然后, setData({ a: 'a' }, callback) callback 第一次进页面的时候执行了,第二次进来的时候没有执行, 这里面的callback 是一定会执行的吗? 有没有大哥遇到相同的问题的呀?
2018-05-24 - editor组件bug,长按出现“粘贴,全选”,手指离开后会消失,很难粘贴?
文档中的示例代码 demo 就是这样 https://developers.weixin.qq.com/miniprogram/dev/component/editor.html [图片] [图片]
2022-11-01 - editor组件和相关的API(EditorContext)可否安排升级一下?
editor组件已经上线很久了(基础库2.7.0开始就支持),但貌似一直没见怎么更新升级过,现在的版本只能说能满足“基础”使用,但在应付一些“重度依赖”编辑器功能和性能的场景,还是有种“很吃力”的感觉。 我厂有个小程序(叫“小蜜笔记”),在开发和使用的过程中,就发现有几个功能和性能是急需升级解决的,相信它们也是大多数其他依赖编辑器的工具需要的功能: 功能方面: 1、需支持插入原生视频(现在只能插入图片模拟); 2、Mac版微信支持极差(如插入图片不能支持正常预览,只显示一个问号?的图标) 3、图片或视频(可以的话)支持位置上下移动 4、可开放更多api给开发者控制图片或视频的样式显示 性能方面: 1、iOS下性能很差,手机正常拍照的图片(4~10M大小),上传超过20张以上(指显示本地路径图片,非网络url图片;手机好点的可以更多一点,但也存在类似问题),小程序基本就会崩溃,导致一些列的操作异常,甚至内容丢失!
2023-02-21