使用小程序进行拖拽排序时,发现由于频繁的setData更改坐标,拖动的时候会产生很大的卡顿,然后发现使用wxs可以解决这个卡顿问题
直接上代码
filter.wxs
// 将需要计算的参数传过来
var windowHeight = 0;//屏幕高度
var rowHeight = 0;//每一项的高度
var startY = 0;//移动定位的top 位置
var scrollViewY = 0;//scroll-view列表顶部距离屏幕顶部距离 - 每一项高度的一半
var showScrollTop = 0;//滚动条滚动距离
var initialIndex = -1;//初始索引
var moveoutindex = -1;//移动到哪个索引
var instances = [], instanceLen;
function startYFun() {
return startY;
}
// 滚动条位置
function scrolltoupper(e, ownerInstance) {
showScrollTop = e.detail.scrollTop;
ownerInstance.callMethod('showScrollTopFun', {
showScrollTop: showScrollTop
});
};
// 长按事件
function onLongPress(e, ownerInstance) {
// 震动
ownerInstance.callMethod('triggerShake');
// 参数
rowHeight = e.currentTarget.dataset.rowheight;
scrollViewY = e.currentTarget.dataset.scrollviewy;
startY = e.touches[0].clientY - rowHeight / 2; // 距离屏幕顶部高度-每一项高度的一半
moveoutindex = parseInt((startY + showScrollTop - scrollViewY) / rowHeight);
initialIndex = e.currentTarget.dataset.index;
if (initialIndex <= moveoutindex) moveoutindex++;
// startYFun();
// 传参执行js方法onLongPressWxs
ownerInstance.callMethod('onLongPressWxs', {
initialIndex: initialIndex,
moveoutindex: moveoutindex
});
instances = ownerInstance.selectAllComponents('.forItem.itemExist'), instanceLen = instances.length;
// for (var i = 0; i < instanceLen; i++) {
var instance = instances[initialIndex];
instance.setStyle({
'top': startY + 'px',
})
// }
}
// 移动或移动结束事件
function listitemmove(e, ownerInstance) {
if (initialIndex == -1) return;
if (e.type == "touchmove") {
startY = e.touches[0].clientY - rowHeight / 2; // 距离屏幕顶部高度-每一项高度的一半
moveoutindex = parseInt((startY + showScrollTop - scrollViewY) / rowHeight);
if (moveoutindex <= 0) {
moveoutindex = 0;
}
if (initialIndex <= moveoutindex) moveoutindex++;
// startYFun();
ownerInstance.callMethod('listitemmoveWxs', {
moveoutindex: moveoutindex
});
// for (var i = 0; i < instanceLen; i++) {
var instance = instances[initialIndex];
instance.setStyle({
'top': startY + 'px',
})
// }
} else {
ownerInstance.callMethod('listiteendWxs');
moveoutindex = -1;
initialIndex = -1;
}
}
// 触摸被打断
function touchcancel(e, ownerInstance) {
console.log("触摸被打断=========================")
ownerInstance.callMethod('listiteendWxs');
moveoutindex = -1;
initialIndex = -1;
}
module.exports = {
onLongPress: onLongPress,
listitemmove: listitemmove,
startYFun: startYFun,
scrolltoupper: scrolltoupper,
touchcancel: touchcancel
};
wxml
<wxs src="./filter.wxs" module="filter" />
<view class="h100">模拟头部</view>
<scroll-view class="scrollList" scroll-y='{{moveoutindex == -1}}' style="max-height: calc(100vh - 100rpx);" bindscroll="{{filter.scrolltoupper}}">
<block wx:for="{{scrollSortList}}" wx:key="index" wx:for-item="item" >
<view class="forItem" style="display: {{moveoutindex == index ? 'block' : 'none'}};"></view>
<view class="forItem itemExist"
data-index='{{index}}' catch:longpress="{{filter.onLongPress}}" bindtouchmove="{{filter.listitemmove}}" bindtouchend="{{filter.listitemmove}}" bind:touchcancel="{{filter.touchcancel}}"
data-rowheight="{{rowHeight}}" data-showscrolltop="{{showScrollTop}}" data-scrollviewy="{{scrollViewY}}" data-windowheight="{{windowHeight}}"
style="left:32rpx;right:32rpx;{{initialIndex==index ? ('position:fixed;box-shadow: 10rpx 0rpx 20rpx 0rpx rgba(51, 137, 255, 0.2);'):''}}">
<text class="sort">{{item.sort}}</text>
<text class="name">第{{item.name }}个</text>
</view>
</block>
<view class="forItem" style="display: {{moveoutindex >= scrollSortList.length ? 'block' : 'none'}};"></view>
</scroll-view>
js
const app = getApp()
Component({
data: {
scrollSortList: [
{
name: '一',
sort: 1
},
{
name: '二',
sort: 2
},
{
name: '三',
sort: 3
},
{
name: '四',
sort: 4
},
{
name: '五',
sort: 5
},
{
name: '六',
sort: 6
},
],
windowHeight: 0, //屏幕高度
rowHeight: 0, //每一项的高度
startY: 0, //移动定位的top 位置
scrollViewY: 0, //scroll-view列表顶部距离屏幕顶部距离 - 每一项高度的一半
showScrollTop: 0, //滚动条滚动距离
initialIndex: -1, //初始索引
moveoutindex: -1, //移动到哪个索引
},
attached: function () {
let rowHeight = this.rpxTorpx(80); // 对应wxss里面.forItem的高度80rpx
this.setData({
rowHeight: rowHeight,
windowHeight: wx.getSystemInfoSync().windowHeight
})
this.queryMultipleNodes();
},
methods: {
// rpx 转换为 px ,传参类型是数字(Number)
rpxTorpx(rpx){
let deviceWidth = wx.getSystemInfoSync().windowWidth; //获取设备屏幕宽度
let px = (deviceWidth/750)*Number(rpx);
return px;
},
showScrollTopFun(obj) {
this.data.showScrollTop = obj.showScrollTop;
},
// 获取scroll-view列表顶部距离屏幕顶部距离
queryMultipleNodes () {
try {
let that = this;
const query = wx.createSelectorQuery().in(this)
query.select('.scrollList').boundingClientRect(function(res){
res.top // 这个组件内 .scrollList 节点的上边界坐标
console.log(res.top, 'res.top', res)
that.setData({
scrollViewY: res.top - that.data.rowHeight / 2
})
}).exec()
} catch (error) {
console.log(error, "获取scroll-view列表顶部距离屏幕顶部距离失败");
wx.showToast({
title: "获取位置失败",
icon: 'none',
})
}
},
// 震动
triggerShake() {
wx.vibrateShort({
success: res => {
},
fail: err => {
wx.vibrateLong({});
}
});
},
touchcancel(e) {
console.log("被打断了")
},
// 长按
onLongPressWxs(obj) {
this.setData({
initialIndex: obj.initialIndex,
moveoutindex: obj.moveoutindex,
});
this.moveoutindex = obj.moveoutindex;
},
// 移动
listitemmoveWxs(obj) {
if (this.data.moveoutindex != obj.moveoutindex && obj.moveoutindex <= this.data.scrollSortList.length) {
this.triggerShake();//震动
this.setData({
moveoutindex: obj.moveoutindex,
});
this.moveoutindex = obj.moveoutindex;
}
},
// 结束
listiteendWxs() {
let index = this.data.initialIndex,
score = this.data.scrollSortList;
let data = {
...score[index]
};
score.splice(index, 1);
if (index <= this.moveoutindex - 1) this.moveoutindex--;
score.splice(this.moveoutindex, 0, data);
score.forEach((itemScore, indexScore) => {
itemScore.sort = indexScore + 1;
})
this.setData({
scrollSortList: score,
});
if (this.data.initialIndex + 1 !== this.data.moveoutindex) {
this.triggerShake();//震动
};
this.setData({
moveoutindex: -1,
initialIndex: -1
});
},
}
})
wxss
.scrollList {
border-top: 1rpx solid #f5f7fa;
}
.scrollList .forItem {
height: 80rpx;
border-bottom: 1rpx solid #f5f7fa;
display: flex;
align-items: center;
user-select: none;
}
.scrollList .forItem .sort {
width: 48rpx;
height: 40rpx;
border: 1rpx solid #b8cae6;
border-radius: 9rpx;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
font-size: 22rpx;
font-weight: bold;
color: #3489ff;
margin-right: 20rpx;
}
.h100 {
height: 100rpx;
}