uview-plus 3.4.70 → 3.4.71

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,8 @@
1
+ ## 3.4.71(2025-08-05)
2
+ feat: 新增virtual-list虚拟列表组件
3
+
4
+ feat: 新增pull-refresh下拉刷新结合虚拟列表使用
5
+
1
6
  ## 3.4.70(2025-08-05)
2
7
  fix: 修复qrcode组件长按事件传入错误cid导致的报错
3
8
 
@@ -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,186 @@
1
+ <template>
2
+ <view class="u-virtual-list" :style="{ height: addUnit(height) }">
3
+ <scroll-view
4
+ class="virtual-scroll-container"
5
+ :scroll-y="true"
6
+ :scroll-top="scrollTop"
7
+ :style="{ height: '100%' }"
8
+ @scroll="handleScroll"
9
+ touchmove.stop.prevent="handleTouchMove"
10
+ >
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
+ return Math.ceil(this.containerHeight / this.itemHeight)
85
+ },
86
+ // 可视项数量
87
+ visibleCount() {
88
+ return this.remain + this.buffer
89
+ },
90
+ // 可视项
91
+ visibleItems() {
92
+ const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
93
+ const end = Math.min(this.listData.length, start + this.visibleCount)
94
+
95
+ return this.listData.slice(start, end).map((item, index) => {
96
+ return {
97
+ ...item,
98
+ _virtualIndex: start + index
99
+ }
100
+ })
101
+ },
102
+ // 顶部占位高度
103
+ topPlaceholderHeight() {
104
+ const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
105
+ return start * this.itemHeight
106
+ },
107
+ // 底部占位高度
108
+ bottomPlaceholderHeight() {
109
+ const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
110
+ const end = Math.min(this.listData.length, start + this.visibleCount)
111
+ return (this.listData.length - end) * this.itemHeight
112
+ }
113
+ },
114
+ watch: {
115
+ listData: {
116
+ handler() {
117
+ this.updateVisibleItems()
118
+ },
119
+ immediate: true
120
+ },
121
+ scrollTop: {
122
+ handler(newVal) {
123
+ this.updateVisibleItems()
124
+ }
125
+ }
126
+ },
127
+ mounted() {
128
+ this.measureContainerHeight()
129
+ },
130
+ methods: {
131
+ addUnit,
132
+
133
+ // 测量容器高度
134
+ measureContainerHeight() {
135
+ const height = this.height
136
+ if (typeof height === 'number') {
137
+ this.containerHeight = height
138
+ return
139
+ }
140
+
141
+ if (typeof height === 'string') {
142
+ if (height.includes('px')) {
143
+ this.containerHeight = parseInt(height)
144
+ } else if (height.includes('%')) {
145
+ // 对于百分比高度,使用默认值或根据父容器计算
146
+ this.containerHeight = 500
147
+ } else {
148
+ const num = parseInt(height)
149
+ this.containerHeight = isNaN(num) ? 500 : num
150
+ }
151
+ } else {
152
+ this.containerHeight = 500
153
+ }
154
+ },
155
+
156
+ getItemKey(item) {
157
+ return item[this.keyField] !== undefined ? item[this.keyField] : item._virtualIndex
158
+ },
159
+
160
+ // 更新可视项
161
+ updateVisibleItems() {
162
+ const index = Math.floor(this.scrollTop / this.itemHeight)
163
+ this.startIndex = Math.max(0, index)
164
+ },
165
+
166
+ // 处理滚动
167
+ handleScroll(e) {
168
+ const scrollTop = e.detail.scrollTop
169
+ this.$emit('scroll', scrollTop)
170
+ },
171
+
172
+ // 处理触摸移动,阻止事件冒泡
173
+ handleTouchMove(e) {
174
+ // 阻止触摸移动事件冒泡到父级,防止触发页面滚动
175
+ e.stopPropagation()
176
+ },
177
+
178
+ // 获取可见项范围
179
+ getVisibleRange() {
180
+ const start = Math.max(0, this.startIndex - Math.floor(this.buffer / 2))
181
+ const end = Math.min(this.listData.length, start + this.visibleCount)
182
+ return { start, end }
183
+ }
184
+ }
185
+ }
186
+ </script>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "uview-plus",
3
3
  "name": "uview-plus",
4
4
  "displayName": "零云®uview-plus3.0重磅发布,全面的Vue3鸿蒙移动组件库。",
5
- "version": "3.4.70",
5
+ "version": "3.4.71",
6
6
  "description": "零云®uview-plus已兼容vue3,全面的组件和便捷的工具会让您信手拈来,如鱼得水。",
7
7
  "keywords": [
8
8
  "uview",