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
@@ -1,3 +1,13 @@
1
+ ## 3.4.72(2025-08-05)
2
+ improvment: 优化virtual-list虚拟列表样式
3
+
4
+ feat: 新增virtual-list虚拟列表演示
5
+
6
+ ## 3.4.71(2025-08-05)
7
+ feat: 新增virtual-list虚拟列表组件
8
+
9
+ feat: 新增pull-refresh下拉刷新结合虚拟列表使用
10
+
1
11
  ## 3.4.70(2025-08-05)
2
12
  fix: 修复qrcode组件长按事件传入错误cid导致的报错
3
13
 
@@ -207,6 +207,10 @@ export default {
207
207
  } else {
208
208
  this.refreshStatus = 'pull'
209
209
  }
210
+
211
+ // 阻止默认滚动行为,防止触发页面级滚动
212
+ e.preventDefault()
213
+ e.stopPropagation()
210
214
  }
211
215
  },
212
216
 
@@ -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.70",
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
- "ui",
12
- "uni-app",
13
- "uni-app",
11
+ "echarts",
14
12
  "ui",
15
13
  "可视化设计"
16
14
  ],