uview-plus 3.4.70 → 3.4.72
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/changelog.md
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<u-pull-refresh
|
|
3
|
+
:refreshing="refreshing"
|
|
4
|
+
:threshold="50"
|
|
5
|
+
@refresh="handleRefresh"
|
|
6
|
+
>
|
|
7
|
+
<u-virtual-list
|
|
8
|
+
ref="virtualList"
|
|
9
|
+
:list-data="listData"
|
|
10
|
+
:item-height="itemHeight"
|
|
11
|
+
:height="height"
|
|
12
|
+
:buffer="buffer"
|
|
13
|
+
:key-field="keyField"
|
|
14
|
+
:scroll-top="scrollTop"
|
|
15
|
+
@scroll="handleScroll"
|
|
16
|
+
>
|
|
17
|
+
<template #default="{ item, index }">
|
|
18
|
+
<slot :item="item" :index="index"></slot>
|
|
19
|
+
</template>
|
|
20
|
+
</u-virtual-list>
|
|
21
|
+
</u-pull-refresh>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script>
|
|
25
|
+
|
|
26
|
+
export default {
|
|
27
|
+
name: 'u-refresh-virtual-list',
|
|
28
|
+
props: {
|
|
29
|
+
// 数据源
|
|
30
|
+
listData: {
|
|
31
|
+
type: Array,
|
|
32
|
+
default: () => []
|
|
33
|
+
},
|
|
34
|
+
// 每项高度(固定高度模式)
|
|
35
|
+
itemHeight: {
|
|
36
|
+
type: Number,
|
|
37
|
+
default: 50
|
|
38
|
+
},
|
|
39
|
+
// 容器高度
|
|
40
|
+
height: {
|
|
41
|
+
type: [String, Number],
|
|
42
|
+
default: '100%'
|
|
43
|
+
},
|
|
44
|
+
// 缓冲区项数
|
|
45
|
+
buffer: {
|
|
46
|
+
type: Number,
|
|
47
|
+
default: 4
|
|
48
|
+
},
|
|
49
|
+
// 索引键名
|
|
50
|
+
keyField: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: 'id'
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
data() {
|
|
56
|
+
return {
|
|
57
|
+
refreshing: false,
|
|
58
|
+
scrollTop: 0
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
methods: {
|
|
62
|
+
handleRefresh() {
|
|
63
|
+
this.refreshing = true
|
|
64
|
+
this.$emit('refresh')
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
handleScroll(scrollTop) {
|
|
68
|
+
this.scrollTop = scrollTop
|
|
69
|
+
this.$emit('scroll', scrollTop)
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
finishRefresh() {
|
|
73
|
+
this.refreshing = false
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
scrollTo(top) {
|
|
77
|
+
this.scrollTop = top
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
scrollToTop() {
|
|
81
|
+
this.scrollTo(0)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="u-virtual-list" :style="{ height: addUnit(height) }" ref="container">
|
|
3
|
+
<scroll-view
|
|
4
|
+
class="virtual-scroll-container"
|
|
5
|
+
:scroll-y="true"
|
|
6
|
+
:scroll-top="scrollTop"
|
|
7
|
+
:style="{ height: '100%' }"
|
|
8
|
+
@scroll="handleScroll"
|
|
9
|
+
>
|
|
10
|
+
<!-- @touchmove.stop.prevent="handleTouchMove" -->
|
|
11
|
+
<view class="scroll-content">
|
|
12
|
+
<!-- 顶部占位 -->
|
|
13
|
+
<view :style="{ height: topPlaceholderHeight + 'px' }"></view>
|
|
14
|
+
|
|
15
|
+
<!-- 可见项 -->
|
|
16
|
+
<view
|
|
17
|
+
v-for="item in visibleItems"
|
|
18
|
+
:key="getItemKey(item)"
|
|
19
|
+
class="list-item"
|
|
20
|
+
:style="{ height: itemHeight + 'px' }"
|
|
21
|
+
>
|
|
22
|
+
<slot :item="item" :index="item._virtualIndex"></slot>
|
|
23
|
+
</view>
|
|
24
|
+
|
|
25
|
+
<!-- 底部占位 -->
|
|
26
|
+
<view :style="{ height: bottomPlaceholderHeight + 'px' }"></view>
|
|
27
|
+
</view>
|
|
28
|
+
</scroll-view>
|
|
29
|
+
</view>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
import { addUnit } from '../../libs/function/index.js'
|
|
34
|
+
|
|
35
|
+
export default {
|
|
36
|
+
name: 'u-virtual-list',
|
|
37
|
+
props: {
|
|
38
|
+
// 数据源
|
|
39
|
+
listData: {
|
|
40
|
+
type: Array,
|
|
41
|
+
default: () => []
|
|
42
|
+
},
|
|
43
|
+
// 每项高度(固定高度模式)
|
|
44
|
+
itemHeight: {
|
|
45
|
+
type: Number,
|
|
46
|
+
default: 50
|
|
47
|
+
},
|
|
48
|
+
// 容器高度
|
|
49
|
+
height: {
|
|
50
|
+
type: [String, Number],
|
|
51
|
+
default: '100%'
|
|
52
|
+
},
|
|
53
|
+
// 缓冲区项数
|
|
54
|
+
buffer: {
|
|
55
|
+
type: Number,
|
|
56
|
+
default: 4
|
|
57
|
+
},
|
|
58
|
+
// 索引键名
|
|
59
|
+
keyField: {
|
|
60
|
+
type: String,
|
|
61
|
+
default: 'id'
|
|
62
|
+
},
|
|
63
|
+
// 当前滚动位置
|
|
64
|
+
scrollTop: {
|
|
65
|
+
type: Number,
|
|
66
|
+
default: 0
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
data() {
|
|
70
|
+
return {
|
|
71
|
+
// 起始索引
|
|
72
|
+
startIndex: 0,
|
|
73
|
+
// 容器实际高度
|
|
74
|
+
containerHeight: 0
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
computed: {
|
|
78
|
+
// 可视区域显示的项数(根据容器实际高度自动计算)
|
|
79
|
+
remain() {
|
|
80
|
+
if (this.containerHeight <= 0) {
|
|
81
|
+
// 默认值,防止除以0
|
|
82
|
+
return Math.ceil(500 / this.itemHeight) || 10
|
|
83
|
+
}
|
|
84
|
+
const calculated = Math.ceil(this.containerHeight / this.itemHeight)
|
|
85
|
+
// 确保至少显示一些项
|
|
86
|
+
return Math.max(1, calculated)
|
|
87
|
+
},
|
|
88
|
+
// 可视项数量
|
|
89
|
+
visibleCount() {
|
|
90
|
+
return this.remain + this.buffer
|
|
91
|
+
},
|
|
92
|
+
// 可视项
|
|
93
|
+
visibleItems() {
|
|
94
|
+
const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
|
|
95
|
+
const end = Math.min(this.listData.length, start + this.visibleCount)
|
|
96
|
+
|
|
97
|
+
return this.listData.slice(start, end).map((item, index) => {
|
|
98
|
+
return {
|
|
99
|
+
...item,
|
|
100
|
+
_virtualIndex: start + index
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
},
|
|
104
|
+
// 顶部占位高度
|
|
105
|
+
topPlaceholderHeight() {
|
|
106
|
+
const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
|
|
107
|
+
return start * this.itemHeight
|
|
108
|
+
},
|
|
109
|
+
// 底部占位高度
|
|
110
|
+
bottomPlaceholderHeight() {
|
|
111
|
+
const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
|
|
112
|
+
const end = Math.min(this.listData.length, start + this.visibleCount)
|
|
113
|
+
return (this.listData.length - end) * this.itemHeight
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
emits: ['update:scrollTop', 'scroll'],
|
|
117
|
+
watch: {
|
|
118
|
+
listData: {
|
|
119
|
+
handler() {
|
|
120
|
+
this.updateVisibleItems()
|
|
121
|
+
},
|
|
122
|
+
immediate: true
|
|
123
|
+
},
|
|
124
|
+
scrollTop: {
|
|
125
|
+
handler(newVal) {
|
|
126
|
+
this.updateVisibleItems()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
mounted() {
|
|
131
|
+
this.measureContainerHeight()
|
|
132
|
+
},
|
|
133
|
+
methods: {
|
|
134
|
+
addUnit,
|
|
135
|
+
|
|
136
|
+
// 测量容器高度
|
|
137
|
+
measureContainerHeight() {
|
|
138
|
+
// 使用 uni.createSelectorQuery 获取实际高度
|
|
139
|
+
this.$nextTick(() => {
|
|
140
|
+
// #ifdef H5
|
|
141
|
+
if (this.$refs.container) {
|
|
142
|
+
const element = this.$refs.container.$el || this.$refs.container
|
|
143
|
+
this.containerHeight = element.offsetHeight || 500
|
|
144
|
+
}
|
|
145
|
+
// #endif
|
|
146
|
+
|
|
147
|
+
// #ifndef H5
|
|
148
|
+
const query = uni.createSelectorQuery().in(this)
|
|
149
|
+
query.select('.u-virtual-list').boundingClientRect(rect => {
|
|
150
|
+
if (rect) {
|
|
151
|
+
this.containerHeight = rect.height || 500
|
|
152
|
+
} else {
|
|
153
|
+
// 如果无法获取实际高度,使用默认计算
|
|
154
|
+
this.containerHeight = this.calculateDefaultHeight()
|
|
155
|
+
}
|
|
156
|
+
}).exec()
|
|
157
|
+
// #endif
|
|
158
|
+
})
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
// 计算默认高度
|
|
162
|
+
calculateDefaultHeight() {
|
|
163
|
+
const height = this.height
|
|
164
|
+
if (typeof height === 'number') {
|
|
165
|
+
return height
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (typeof height === 'string') {
|
|
169
|
+
if (height.includes('px')) {
|
|
170
|
+
return parseInt(height) || 500
|
|
171
|
+
} else if (height.includes('vh')) {
|
|
172
|
+
// 处理视口高度单位
|
|
173
|
+
const vh = parseInt(height)
|
|
174
|
+
return isNaN(vh) ? 500 : (vh / 100) * this.getViewportHeight()
|
|
175
|
+
} else if (height.includes('%')) {
|
|
176
|
+
// 百分比高度,使用默认值
|
|
177
|
+
return 500
|
|
178
|
+
} else {
|
|
179
|
+
const num = parseInt(height)
|
|
180
|
+
return isNaN(num) ? 500 : num
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return 500
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
// 获取视口高度
|
|
188
|
+
getViewportHeight() {
|
|
189
|
+
// #ifdef H5
|
|
190
|
+
return window.innerHeight
|
|
191
|
+
// #endif
|
|
192
|
+
|
|
193
|
+
// #ifndef H5
|
|
194
|
+
try {
|
|
195
|
+
const res = uni.getSystemInfoSync()
|
|
196
|
+
return res.windowHeight
|
|
197
|
+
} catch (e) {
|
|
198
|
+
return 600 // 默认值
|
|
199
|
+
}
|
|
200
|
+
// #endif
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
getItemKey(item) {
|
|
204
|
+
return item[this.keyField] !== undefined ? item[this.keyField] : item._virtualIndex
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// 更新可视项
|
|
208
|
+
updateVisibleItems() {
|
|
209
|
+
const index = Math.floor(this.scrollTop / this.itemHeight)
|
|
210
|
+
this.startIndex = Math.max(0, index)
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
// 处理滚动
|
|
214
|
+
handleScroll(e) {
|
|
215
|
+
const scrollTop = e.detail.scrollTop
|
|
216
|
+
this.$emit('update:scrollTop', scrollTop)
|
|
217
|
+
this.$emit('scroll', scrollTop)
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
// 处理触摸移动,阻止事件冒泡
|
|
221
|
+
handleTouchMove(e) {
|
|
222
|
+
// 阻止触摸移动事件冒泡到父级,防止触发页面滚动
|
|
223
|
+
e.stopPropagation()
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
// 获取可见项范围
|
|
227
|
+
getVisibleRange() {
|
|
228
|
+
const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
|
|
229
|
+
const end = Math.min(this.listData.length, start + this.visibleCount)
|
|
230
|
+
return { start, end }
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
</script>
|
|
235
|
+
|
|
236
|
+
<style scoped lang="scss">
|
|
237
|
+
.u-virtual-list {
|
|
238
|
+
position: relative;
|
|
239
|
+
overflow: hidden;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.virtual-scroll-container {
|
|
243
|
+
height: 100%;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.scroll-content {
|
|
247
|
+
position: relative;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.list-item {
|
|
251
|
+
will-change: transform;
|
|
252
|
+
}
|
|
253
|
+
</style>
|
package/package.json
CHANGED
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
"id": "uview-plus",
|
|
3
3
|
"name": "uview-plus",
|
|
4
4
|
"displayName": "零云®uview-plus3.0重磅发布,全面的Vue3鸿蒙移动组件库。",
|
|
5
|
-
"version": "3.4.
|
|
6
|
-
"description": "零云®uview-plus已兼容vue3
|
|
5
|
+
"version": "3.4.72",
|
|
6
|
+
"description": "零云®uview-plus已兼容vue3,100+全面的组件和便捷的工具会让您信手拈来,如鱼得水。",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"uview",
|
|
9
9
|
"uview-plus",
|
|
10
10
|
"ui",
|
|
11
|
-
"
|
|
12
|
-
"uni-app",
|
|
13
|
-
"uni-app",
|
|
11
|
+
"echarts",
|
|
14
12
|
"ui",
|
|
15
13
|
"可视化设计"
|
|
16
14
|
],
|