rrj-astra-ui 1.1.13 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/AuiListItem.vue +31 -104
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view class="aui-list-item" ref="listItemRef">
|
|
3
|
+
<!-- 给外层加 touchable 确保触摸事件触发(uni-app 小程序端兼容) -->
|
|
3
4
|
<view class="aui-list-item-content-wrapper"
|
|
4
5
|
:style="{ transform: `translateX(${offsetX}px)` }"
|
|
5
6
|
@touchstart="onTouchStart"
|
|
6
7
|
@touchmove="onTouchMove"
|
|
7
|
-
@touchend="onTouchEnd"
|
|
8
|
+
@touchend="onTouchEnd"
|
|
9
|
+
touch-action="pan-x"> <!-- 明确支持水平滑动 -->
|
|
8
10
|
<view class="aui-list-item_befor">
|
|
9
11
|
<slot name="befor"></slot>
|
|
10
12
|
</view>
|
|
@@ -30,8 +32,8 @@
|
|
|
30
32
|
</template>
|
|
31
33
|
|
|
32
34
|
<script setup>
|
|
33
|
-
import { defineProps, ref, onMounted, onUnmounted
|
|
34
|
-
const __name = 'AuiListItem';
|
|
35
|
+
import { defineProps, ref, onMounted, onUnmounted } from 'vue';
|
|
36
|
+
const __name = 'AuiListItem';
|
|
35
37
|
|
|
36
38
|
defineOptions({
|
|
37
39
|
name: __name
|
|
@@ -44,159 +46,78 @@ const props = defineProps({
|
|
|
44
46
|
allowSlide: { type: Boolean, default: true }
|
|
45
47
|
});
|
|
46
48
|
|
|
47
|
-
//
|
|
49
|
+
// 滑动核心变量(无任何额外变量)
|
|
48
50
|
const startX = ref(0);
|
|
49
51
|
const offsetX = ref(0);
|
|
50
52
|
const isSliding = ref(false);
|
|
51
53
|
const SLIDE_THRESHOLD = -50;
|
|
52
54
|
const listItemRef = ref(null);
|
|
53
|
-
// 标记当前组件是否已展开
|
|
54
|
-
const isOpened = ref(false);
|
|
55
55
|
|
|
56
|
-
// ##########
|
|
57
|
-
const closeAllOpenedItems = (currentDom) => {
|
|
58
|
-
// 找到所有aui-list-item组件DOM
|
|
59
|
-
const allItems = document.querySelectorAll('.aui-list-item');
|
|
60
|
-
if (!allItems || allItems.length === 0) return;
|
|
61
|
-
|
|
62
|
-
allItems.forEach(item => {
|
|
63
|
-
// 跳过当前正在触摸的项
|
|
64
|
-
if (item === currentDom) return;
|
|
65
|
-
|
|
66
|
-
// 找到子元素的偏移量和状态
|
|
67
|
-
const contentWrapper = item.querySelector('.aui-list-item-content-wrapper');
|
|
68
|
-
if (!contentWrapper) return;
|
|
69
|
-
|
|
70
|
-
// 强制重置偏移和状态(直接操作DOM+组件内部状态)
|
|
71
|
-
contentWrapper.style.transform = 'translateX(0px)';
|
|
72
|
-
// 找到对应的组件实例(通过DOM绑定的属性)
|
|
73
|
-
const itemInstance = item.__auiListItemInstance;
|
|
74
|
-
if (itemInstance) {
|
|
75
|
-
itemInstance.offsetX.value = 0;
|
|
76
|
-
itemInstance.isSliding.value = false;
|
|
77
|
-
itemInstance.isOpened.value = false;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// 触摸开始:先收回其他项,再执行原有逻辑
|
|
56
|
+
// ########## 最纯粹的滑动逻辑(无任何联动,保证能滑) ##########
|
|
83
57
|
const onTouchStart = (e) => {
|
|
84
58
|
if (!props.allowSlide) return;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
closeAllOpenedItems(listItemRef.value);
|
|
59
|
+
// 强制获取触摸点(兼容uni-app 小程序端触摸事件格式)
|
|
60
|
+
const touch = e.touches || e.changedTouches;
|
|
61
|
+
if (!touch || touch.length === 0) return;
|
|
89
62
|
|
|
90
|
-
|
|
91
|
-
startX.value = e.touches[0].clientX;
|
|
63
|
+
startX.value = touch[0].clientX;
|
|
92
64
|
offsetX.value = 0;
|
|
93
65
|
isSliding.value = false;
|
|
94
|
-
isOpened.value = false;
|
|
95
66
|
};
|
|
96
67
|
|
|
97
|
-
// 触摸移动:完全保留你的原有逻辑,右滑恢复正常
|
|
98
68
|
const onTouchMove = (e) => {
|
|
99
69
|
if (!props.allowSlide) return;
|
|
100
|
-
|
|
70
|
+
// 强制获取触摸点(兼容uni-app 小程序端)
|
|
71
|
+
const touch = e.touches || e.changedTouches;
|
|
72
|
+
if (!touch || touch.length === 0) return;
|
|
73
|
+
|
|
74
|
+
const currentX = touch[0].clientX;
|
|
101
75
|
const diffX = currentX - startX.value;
|
|
102
76
|
|
|
103
|
-
//
|
|
77
|
+
// 左滑逻辑(正常更新偏移)
|
|
104
78
|
if (diffX < 0) {
|
|
105
79
|
offsetX.value = diffX;
|
|
106
80
|
if (diffX < SLIDE_THRESHOLD) {
|
|
107
81
|
isSliding.value = true;
|
|
108
82
|
}
|
|
109
83
|
}
|
|
110
|
-
|
|
84
|
+
|
|
85
|
+
// 右滑逻辑(正常重置)
|
|
111
86
|
if (diffX > 0) {
|
|
112
87
|
offsetX.value = 0;
|
|
113
88
|
isSliding.value = false;
|
|
114
|
-
isOpened.value = false;
|
|
115
89
|
}
|
|
116
90
|
};
|
|
117
91
|
|
|
118
|
-
// 触摸结束:保留原有逻辑,绑定组件实例到DOM
|
|
119
92
|
const onTouchEnd = () => {
|
|
120
93
|
if (!props.allowSlide) return;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// 原有逻辑,无改动
|
|
94
|
+
// 纯粹的滑动结束定位(无任何额外逻辑)
|
|
124
95
|
if (offsetX.value < SLIDE_THRESHOLD) {
|
|
125
96
|
offsetX.value = -150;
|
|
126
97
|
isSliding.value = true;
|
|
127
|
-
isOpened.value = true; // 标记当前项已展开
|
|
128
98
|
} else {
|
|
129
99
|
offsetX.value = 0;
|
|
130
100
|
isSliding.value = false;
|
|
131
|
-
isOpened.value = false;
|
|
132
101
|
}
|
|
133
|
-
|
|
134
|
-
// ########## 绑定组件实例到DOM,供其他项收回时调用(验证生效) ##########
|
|
135
|
-
listItemRef.value.__auiListItemInstance = {
|
|
136
|
-
offsetX,
|
|
137
|
-
isSliding,
|
|
138
|
-
isOpened
|
|
139
|
-
};
|
|
140
102
|
};
|
|
141
103
|
|
|
142
|
-
//
|
|
104
|
+
// 简单重置方法
|
|
143
105
|
const resetSlide = () => {
|
|
144
106
|
if (!props.allowSlide) return;
|
|
145
107
|
offsetX.value = 0;
|
|
146
108
|
isSliding.value = false;
|
|
147
|
-
isOpened.value = false;
|
|
148
109
|
};
|
|
149
110
|
|
|
150
|
-
//
|
|
151
|
-
const handlePageClick = (e) => {
|
|
152
|
-
if (!listItemRef.value || !isSliding.value) return;
|
|
153
|
-
|
|
154
|
-
const itemRect = listItemRef.value.getBoundingClientRect();
|
|
155
|
-
const clickX = e.clientX || e.touches?.[0]?.clientX;
|
|
156
|
-
const clickY = e.clientY || e.touches?.[0]?.clientY;
|
|
157
|
-
|
|
158
|
-
if (
|
|
159
|
-
clickX < itemRect.left ||
|
|
160
|
-
clickX > itemRect.right ||
|
|
161
|
-
clickY < itemRect.top ||
|
|
162
|
-
clickY > itemRect.bottom
|
|
163
|
-
) {
|
|
164
|
-
resetSlide();
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
// 挂载:绑定监听+DOM实例,验证生效
|
|
111
|
+
// 仅保留必要的外部点击收回(无多余监听)
|
|
169
112
|
onMounted(() => {
|
|
170
|
-
if (!listItemRef.value) return;
|
|
171
|
-
|
|
172
|
-
// 保留你的原有监听
|
|
173
113
|
uni.onClickOutside(listItemRef, resetSlide);
|
|
174
|
-
window.addEventListener('click', handlePageClick);
|
|
175
|
-
window.addEventListener('touchstart', handlePageClick);
|
|
176
|
-
|
|
177
|
-
// 绑定组件实例到DOM
|
|
178
|
-
listItemRef.value.__auiListItemInstance = {
|
|
179
|
-
offsetX,
|
|
180
|
-
isSliding,
|
|
181
|
-
isOpened
|
|
182
|
-
};
|
|
183
114
|
});
|
|
184
115
|
|
|
185
|
-
// 卸载:清理监听+DOM实例,验证生效
|
|
186
116
|
onUnmounted(() => {
|
|
187
|
-
if (!listItemRef.value) return;
|
|
188
|
-
|
|
189
|
-
// 保留你的原有清理
|
|
190
117
|
uni.offClickOutside(listItemRef, resetSlide);
|
|
191
|
-
window.removeEventListener('click', handlePageClick);
|
|
192
|
-
window.removeEventListener('touchstart', handlePageClick);
|
|
193
|
-
|
|
194
|
-
// 清理DOM上的组件实例,避免内存泄漏
|
|
195
|
-
delete listItemRef.value.__auiListItemInstance;
|
|
196
118
|
});
|
|
197
119
|
</script>
|
|
198
120
|
|
|
199
|
-
<!-- 样式部分:完全保留你的原有代码,验证生效 -->
|
|
200
121
|
<style scoped lang="scss">
|
|
201
122
|
@import '../style.scss';
|
|
202
123
|
.aui-list-item {
|
|
@@ -206,12 +127,18 @@ onUnmounted(() => {
|
|
|
206
127
|
border-bottom: 1px solid #F3F4F6;
|
|
207
128
|
position: relative;
|
|
208
129
|
overflow: hidden;
|
|
130
|
+
/* 确保容器能接收触摸事件 */
|
|
131
|
+
touch-action: pan-x;
|
|
132
|
+
pointer-events: auto;
|
|
209
133
|
}
|
|
210
134
|
.aui-list-item-content-wrapper {
|
|
211
135
|
display: flex;
|
|
212
|
-
// align-items: center;
|
|
213
136
|
width: 100%;
|
|
214
|
-
transition: transform 0.3s;
|
|
137
|
+
transition: transform 0.3s ease; /* 顺滑过渡,保证滑动视觉正常 */
|
|
138
|
+
/* 确保内容区能接收触摸事件 */
|
|
139
|
+
touch-action: pan-x;
|
|
140
|
+
pointer-events: auto;
|
|
141
|
+
transform: translateX(0px); /* 初始偏移 */
|
|
215
142
|
}
|
|
216
143
|
.aui-list-item_befor {
|
|
217
144
|
margin:0 10px;
|
|
@@ -241,7 +168,7 @@ onUnmounted(() => {
|
|
|
241
168
|
right: 0;
|
|
242
169
|
top: 0;
|
|
243
170
|
bottom: 0;
|
|
244
|
-
width: 150px;
|
|
171
|
+
width: 150px;
|
|
245
172
|
background-color: #f0f0f0;
|
|
246
173
|
display: flex;
|
|
247
174
|
align-items: center;
|