1 | import { ComponentType } from 'react'
|
2 | import { BaseEventOrigFunction, CommonEventFunction, StandardProps } from './common'
|
3 | interface ScrollViewProps extends StandardProps {
|
4 | /** 允许横向滚动
|
5 | * @default false
|
6 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
7 | * @rn 二选一
|
8 | */
|
9 | scrollX?: boolean
|
10 | /** 允许纵向滚动
|
11 | * @default false
|
12 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
13 | * @rn 二选一
|
14 | */
|
15 | scrollY?: boolean
|
16 | /** 距顶部/左边多远时(单位px),触发 scrolltoupper 事件
|
17 | * @default 50
|
18 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
19 | */
|
20 | upperThreshold?: number
|
21 | /** 距底部/右边多远时(单位px),触发 scrolltolower 事件
|
22 | * @default 50
|
23 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
24 | */
|
25 | lowerThreshold?: number
|
26 | /** 设置竖向滚动条位置
|
27 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
28 | */
|
29 | scrollTop?: number
|
30 | /** 设置横向滚动条位置
|
31 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
32 | */
|
33 | scrollLeft?: number
|
34 | /** 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素
|
35 | * @supported weapp, alipay, swan, tt, qq, jd, h5, harmony_hybrid
|
36 | */
|
37 | scrollIntoView?: string
|
38 | /** 在设置滚动条位置时使用动画过渡
|
39 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
40 | * @default false
|
41 | */
|
42 | scrollWithAnimation?: boolean
|
43 | /** iOS 点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向
|
44 | * @supported weapp, alipay, swan, qq, jd, rn
|
45 | * @default false
|
46 | */
|
47 | enableBackToTop?: boolean
|
48 | /** 启用 flexbox 布局。开启后,当前节点声明了 `display: flex` 就会成为 flex container,并作用于其孩子节点。
|
49 | * @supported weapp, jd
|
50 | * @default false
|
51 | */
|
52 | enableFlex?: boolean
|
53 | /** 开启 scroll anchoring 特性,即控制滚动位置不随内容变化而抖动,仅在 iOS 下生效,安卓下可参考 CSS `overflow-anchor` 属性。
|
54 | * @supported weapp
|
55 | * @default false
|
56 | */
|
57 | scrollAnchoring?: boolean
|
58 | /** 开启自定义下拉刷新
|
59 | * @supported weapp
|
60 | * @default false
|
61 | */
|
62 | refresherEnabled?: boolean
|
63 | /** 设置自定义下拉刷新阈值
|
64 | * @supported weapp
|
65 | * @default 45
|
66 | */
|
67 | refresherThreshold?: number
|
68 | /** 设置自定义下拉刷新默认样式,支持设置 `black | white | none`, none 表示不使用默认样式
|
69 | * @supported weapp
|
70 | * @default 'black'
|
71 | */
|
72 | refresherDefaultStyle?: string
|
73 | /** 设置自定义下拉刷新区域背景颜色
|
74 | * @supported weapp
|
75 | * @default '#FFF'
|
76 | */
|
77 | refresherBackground?: string
|
78 | /** 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
|
79 | * @supported weapp
|
80 | * @default false
|
81 | */
|
82 | refresherTriggered?: boolean
|
83 | /** 启用 scroll-view 增强特性
|
84 | * @supported weapp, swan
|
85 | * @default false
|
86 | */
|
87 | enhanced?: boolean
|
88 | /** 使 scroll-view 下的 position sticky 特性生效,否则滚动一屏后 sticky 元素会被隐藏
|
89 | * @supported weapp
|
90 | * @default false
|
91 | */
|
92 | usingSticky?: boolean
|
93 | /** iOS 下 scroll-view 边界弹性控制 (同时开启 enhanced 属性后生效)
|
94 | * @supported weapp, swan
|
95 | * @default true
|
96 | */
|
97 | bounces?: boolean
|
98 | /** 滚动条显隐控制 (同时开启 enhanced 属性后生效)
|
99 | * @supported weapp
|
100 | * @default true
|
101 | */
|
102 | showScrollbar?: boolean
|
103 | /** 分页滑动效果 (同时开启 enhanced 属性后生效)
|
104 | * @supported weapp
|
105 | * @default false
|
106 | */
|
107 | pagingEnabled?: boolean
|
108 | /** boolean false 滑动减速速率控制 (同时开启 enhanced 属性后生效)
|
109 | * @supported weapp
|
110 | * @default false
|
111 | */
|
112 | fastDeceleration?: boolean
|
113 | /** 当 scroll-with-animation设置为 true 时,可以设置 scroll-animation-duration 来控制动画的执行时间,单位 ms。
|
114 | * @supported alipay
|
115 | */
|
116 | scrollAnimationDuration?: string
|
117 | /** 纵向滚动时,当滚动到顶部或底部时,强制禁止触发页面滚动,仍然只触发 scroll-view 自身的滚动。
|
118 | * @supported alipay
|
119 | * @default false
|
120 | */
|
121 | trapScroll?: string
|
122 | /** 发生滚动前,对滚动方向进行判断,当方向是顶部/左边时,如果值为 always 将始终禁止滚动,如果值为 out-of-bounds 且当前已经滚动到顶部/左边,禁止滚动。
|
123 | * @supported alipay
|
124 | */
|
125 | disableLowerScroll?: string
|
126 | /** 发生滚动前,对滚动方向进行判断,当方向是底部/右边时,如果值为 always 将始终禁止滚动,如果值为 out-of-bounds 且当前已经滚动到底部/右边,禁止滚动。
|
127 | * @supported alipay
|
128 | */
|
129 | disableUpperScroll?: string
|
130 | /** 无障碍访问,(属性)元素的额外描述
|
131 | * @supported qq
|
132 | */
|
133 | ariaLabel?: string
|
134 | /** 开启 passive 特性,能优化一定的滚动性能
|
135 | * @supported weapp
|
136 | * @default false
|
137 | */
|
138 | enablePassive?: boolean
|
139 | /** 渲染模式
|
140 | * list - 列表模式。只会渲染在屏节点,会根据直接子节点是否在屏来按需渲染,若只有一个直接子节点则性能会退化
|
141 | * custom - 自定义模式。只会渲染在屏节点,子节点可以是 sticky-section list-view grid-view 等组件
|
142 | * @supported weapp
|
143 | * @default 'list'
|
144 | */
|
145 | type?: 'list' | 'custom'
|
146 | /** 是否反向滚动。一般初始滚动位置是在顶部,反向滚动则是在底部。
|
147 | * @supported weapp
|
148 | * @default false
|
149 | */
|
150 | reverse?: boolean
|
151 | /** 是否对溢出进行裁剪,默认开启
|
152 | * @supported weapp
|
153 | * @default true
|
154 | */
|
155 | clip?: boolean
|
156 | /** 指定视口外渲染区域的距离,默认情况下视口外节点不渲染。指定 cache-extent 可优化滚动体验和加载速度,但会提高内存占用且影响首屏速度,可按需启用。
|
157 | * @supported weapp
|
158 | */
|
159 | cacheExtent?: number
|
160 | /** 指定 scroll-view 触发滚动的最小拖动距离。仅在 scroll-view 和其他组件存在手势冲突时使用,可通过调整该属性使得滚动更加灵敏。
|
161 | * @supported weapp
|
162 | * @default 18
|
163 | */
|
164 | minDragDistance?: number
|
165 | /** 长度为 4 的数组,按 top、right、bottom、left 顺序指定内边距
|
166 | * @supported weapp
|
167 | * @default [0,0,0,0]
|
168 | */
|
169 | padding?: [number, number, number, number]
|
170 | /** 只 scroll-into-view 到 cacheExtent 以内的目标节点,性能更佳
|
171 | * @supported weapp
|
172 | * @default false
|
173 | */
|
174 | scrollIntoViewWithinExtent?: boolean
|
175 | /** 指定 scroll-into-view 目标节点在视口内的位置。
|
176 | * start - 目标节点显示在视口开始处
|
177 | * center - 目标节点显示在视口中间
|
178 | * end - 目标节点显示在视口结束处
|
179 | * nearest - 目标节点在就近的视口边缘显示,若节点已在视口内则不触发滚动
|
180 | * @supported weapp, h5, harmony_hybrid
|
181 | * @default 'start'
|
182 | */
|
183 | scrollIntoViewAlignment?: 'start' | 'center' | 'end' | 'nearest'
|
184 | /** 开启下拉二级能力
|
185 | * @supported weapp
|
186 | * @default false
|
187 | */
|
188 | refresherTwoLevelEnabled?: boolean
|
189 | /** 设置打开/关闭二级
|
190 | * @supported weapp
|
191 | * @default false
|
192 | */
|
193 | refresherTwoLevelTriggered?: boolean
|
194 | /** 下拉二级阈值
|
195 | * @supported weapp
|
196 | * @default 150
|
197 | */
|
198 | refresherTwoLevelThreshold?: number
|
199 | /** 滑动返回时关闭二级的阈值
|
200 | * @supported weapp
|
201 | * @default 80
|
202 | */
|
203 | refresherTwoLevelCloseThreshold?: number
|
204 | /** 处于二级状态时是否可滑动
|
205 | * @supported weapp
|
206 | * @default false
|
207 | */
|
208 | refresherTwoLevelScrollEnabled?: boolean
|
209 | /** 惯性滚动是否触发下拉刷新
|
210 | * @supported weapp
|
211 | * @default false
|
212 | */
|
213 | refresherBallisticRefreshEnabled?: boolean
|
214 | /** 即将打开二级时否定住
|
215 | * @supported weapp
|
216 | * @default false
|
217 | */
|
218 | refresherTwoLevelPinned?: boolean
|
219 | /** 滚动到顶部/左边,会触发 scrolltoupper 事件
|
220 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
221 | */
|
222 | onScrollToUpper?: CommonEventFunction
|
223 | /** 滚动到底部/右边,会触发 scrolltolower 事件
|
224 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
225 | */
|
226 | onScrollToLower?: CommonEventFunction
|
227 | /** 滚动时触发
|
228 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony_hybrid
|
229 | */
|
230 | onScroll?: BaseEventOrigFunction<ScrollViewProps.onScrollDetail>
|
231 | /** 滚动开始事件
|
232 | * @supported weapp
|
233 | */
|
234 | onScrollStart?: BaseEventOrigFunction<ScrollViewProps.onScrollDetail>
|
235 | /** 滚动结束事件
|
236 | * @supported weapp
|
237 | */
|
238 | onScrollEnd?: BaseEventOrigFunction<ScrollViewProps.onScrollDetail>
|
239 | /** 自定义下拉刷新控件被下拉
|
240 | * @supported weapp
|
241 | */
|
242 | onRefresherPulling?: CommonEventFunction
|
243 | /** 自定义下拉刷新被触发
|
244 | * @supported weapp
|
245 | */
|
246 | onRefresherRefresh?: CommonEventFunction
|
247 | /** 自定义下拉刷新被复位
|
248 | * @supported weapp
|
249 | */
|
250 | onRefresherRestore?: CommonEventFunction
|
251 | /** 自定义下拉刷新被中止
|
252 | * @supported weapp
|
253 | */
|
254 | onRefresherAbort?: CommonEventFunction
|
255 | /** 自定义下拉刷新即将触发刷新(拖动超过 refresher-threshold 时)的事件
|
256 | * @supported weapp
|
257 | */
|
258 | onRefresherWillRefresh?: CommonEventFunction
|
259 | /** 下拉刷新状态回调
|
260 | * @supported weapp
|
261 | */
|
262 | onRefresherStatusChange?: CommonEventFunction<ScrollViewProps.RefresherStatusChange>
|
263 | /** 滑动开始事件 (同时开启 enhanced 属性后生效)
|
264 | * @supported weapp
|
265 | */
|
266 | onDragStart?: CommonEventFunction<ScrollViewProps.onDragDetail>
|
267 | /** 滑动事件 (同时开启 enhanced 属性后生效)
|
268 | * @supported weapp
|
269 | */
|
270 | onDragging?: CommonEventFunction<ScrollViewProps.onDragDetail>
|
271 | /** 滑动结束事件 (同时开启 enhanced 属性后生效)
|
272 | * @supported weapp
|
273 | */
|
274 | onDragEnd?: CommonEventFunction<ScrollViewProps.onDragDetail>
|
275 | /** 触摸动作开始。
|
276 | * @supported alipay
|
277 | */
|
278 | onTouchStart?: CommonEventFunction
|
279 | /** 触摸后移动。
|
280 | * @supported alipay
|
281 | */
|
282 | onTouchMove?: CommonEventFunction
|
283 | /** 触摸动作结束。
|
284 | * @supported alipay
|
285 | */
|
286 | onTouchEnd?: CommonEventFunction
|
287 | /** 触摸动作被打断,如来电提醒、弹窗。
|
288 | * @supported alipay
|
289 | */
|
290 | onTouchCancel?: CommonEventFunction
|
291 | }
|
292 | declare namespace ScrollViewProps {
|
293 | interface onScrollDetail {
|
294 | /** 横向滚动条位置 */
|
295 | scrollLeft: number
|
296 | /** 竖向滚动条位置 */
|
297 | scrollTop: number
|
298 | /** 滚动条高度 */
|
299 | scrollHeight: number
|
300 | /** 滚动条宽度 */
|
301 | scrollWidth: number
|
302 | deltaX: number
|
303 | deltaY: number
|
304 | isDrag?: boolean
|
305 | }
|
306 | interface onDragDetail {
|
307 | /** 横向滚动条位置 */
|
308 | scrollLeft: number
|
309 | /** 竖向滚动条位置 */
|
310 | scrollTop: number
|
311 | /** 滚动速度 */
|
312 | velocity: number
|
313 | }
|
314 | interface RefresherStatusChange {
|
315 | status: RefreshStatus
|
316 | dy: number
|
317 | }
|
318 | const enum RefreshStatus {
|
319 | // 空闲
|
320 | Idle,
|
321 | // 超过下拉刷新阈值,同 bind:refresherwillRefresh 触发时机
|
322 | CanRefresh,
|
323 | // 下拉刷新,同 bind:refresherrefresh 触发时机
|
324 | Refreshing,
|
325 | // 下拉刷新完成,同 bind:refresherrestore 触发时机
|
326 | Completed,
|
327 | // 下拉刷新失败
|
328 | Failed,
|
329 | // 超过下拉二级阈值
|
330 | CanTwoLevel,
|
331 | // 开始打开二级
|
332 | TwoLevelOpening,
|
333 | // 打开二级
|
334 | TwoLeveling,
|
335 | // 开始关闭二级
|
336 | TwoLevelClosing,
|
337 | }
|
338 | }
|
339 | /** 可滚动视图区域。使用竖向滚动时,需要给scroll-view一个固定高度,通过 WXSS 设置 height。组件属性的长度单位默认为 px
|
340 | *
|
341 | * Tips:
|
342 | * H5 中 ScrollView 组件是通过一个高度(或宽度)固定的容器内部滚动来实现的,因此务必正确的设置容器的高度。例如: 如果 ScrollView 的高度将 body 撑开,就会同时存在两个滚动条(body 下的滚动条,以及 ScrollView 的滚动条)。
|
343 | * 微信小程序 中 ScrollView 组件如果设置 scrollX 横向滚动时,并且子元素为多个时(单个子元素时设置固定宽度则可以正常横向滚动),需要通过 WXSS 设置 `white-space: nowrap` 来保证元素不换行,并对 ScrollView 内部元素设置 `display: inline-block` 来使其能够横向滚动。
|
344 | * @classification viewContainer
|
345 | * @supported weapp, alipay, swan, tt, qq, jd, h5, rn, harmony, harmony_hybrid
|
346 | * @example_react
|
347 | * ```tsx
|
348 | * export default class PageView extends Component {
|
349 | * constructor() {
|
350 | * super(...arguments)
|
351 | * }
|
352 | *
|
353 | * onScrollToUpper() {}
|
354 | *
|
355 | * // or 使用箭头函数
|
356 | * // onScrollToUpper = () => {}
|
357 | *
|
358 | * onScroll(e){
|
359 | * console.log(e.detail)
|
360 | * }
|
361 | *
|
362 | * render() {
|
363 | * const scrollStyle = {
|
364 | * height: '150px'
|
365 | * }
|
366 | * const scrollTop = 0
|
367 | * const Threshold = 20
|
368 | * const vStyleA = {
|
369 | * height: '150px',
|
370 | * 'backgroundColor': 'rgb(26, 173, 25)'
|
371 | * }
|
372 | * const vStyleB = {
|
373 | * height: '150px',
|
374 | * 'backgroundColor': 'rgb(39,130,215)'
|
375 | * }
|
376 | * const vStyleC = {
|
377 | * height: '150px',
|
378 | * 'backgroundColor': 'rgb(241,241,241)',
|
379 | * color: '#333'
|
380 | * }
|
381 | * return (
|
382 | * <ScrollView
|
383 | * className='scrollview'
|
384 | * scrollY
|
385 | * scrollWithAnimation
|
386 | * scrollTop={scrollTop}
|
387 | * style={scrollStyle}
|
388 | * lowerThreshold={Threshold}
|
389 | * upperThreshold={Threshold}
|
390 | * onScrollToUpper={this.onScrollToUpper.bind(this)} // 使用箭头函数的时候 可以这样写 `onScrollToUpper={this.onScrollToUpper}`
|
391 | * onScroll={this.onScroll}
|
392 | * >
|
393 | * <View style={vStyleA}>A</View>
|
394 | * <View style={vStyleB}>B</View>
|
395 | * <View style={vStyleC}>C</View>
|
396 | * </ScrollView>
|
397 | * )
|
398 | * }
|
399 | * }
|
400 | * ```
|
401 | * @example_vue
|
402 | * ```html
|
403 | * <template>
|
404 | * <view class="container">
|
405 | * <view class="page-body">
|
406 | * <view class="page-section">
|
407 | * <view class="page-section-title">
|
408 | * <text>Vertical Scroll - 纵向滚动</text>
|
409 | * </view>
|
410 | * <view class="page-section-spacing">
|
411 | * <scroll-view :scroll-y="true" style="height: 300rpx;" `@scrolltoupper="upper" `@scrolltolower="lower" `@scroll="scroll" :scroll-into-view="toView" :scroll-top="scrollTop">
|
412 | * <view id="demo1" class="scroll-view-item demo-text-1">1</view>
|
413 | * <view id="demo2" class="scroll-view-item demo-text-2">2</view>
|
414 | * <view id="demo3" class="scroll-view-item demo-text-3">3</view>
|
415 | * </scroll-view>
|
416 | * </view>
|
417 | * </view>
|
418 | * <view class="page-section">
|
419 | * <view class="page-section-title">
|
420 | * <text>Horizontal Scroll - 横向滚动</text>
|
421 | * </view>
|
422 | * <view class="page-section-spacing">
|
423 | * <scroll-view class="scroll-view_H" :scroll-x="true" `@scroll="scroll" style="width: 100%">
|
424 | * <view id="demo21" class="scroll-view-item_H demo-text-1">a</view>
|
425 | * <view id="demo22" class="scroll-view-item_H demo-text-2">b</view>
|
426 | * <view id="demo23" class="scroll-view-item_H demo-text-3">c</view>
|
427 | * </scroll-view>
|
428 | * </view>
|
429 | * </view>
|
430 | * </view>
|
431 | * </view>
|
432 | * </template>
|
433 | *
|
434 | * <script>
|
435 | * const order = ['demo1', 'demo2', 'demo3']
|
436 | * export default {
|
437 | * name: 'Index',
|
438 | * data() {
|
439 | * return {
|
440 | * scrollTop: 0,
|
441 | * toView: 'demo2'
|
442 | * }
|
443 | * },
|
444 | *
|
445 | * methods: {
|
446 | * upper(e) {
|
447 | * console.log('upper:', e)
|
448 | * },
|
449 | *
|
450 | * lower(e) {
|
451 | * console.log('lower:', e)
|
452 | * },
|
453 | *
|
454 | * scroll(e) {
|
455 | * console.log('scroll:', e)
|
456 | * }
|
457 | * }
|
458 | * }
|
459 | * </script>
|
460 | *
|
461 | * <style>
|
462 | * .page-section-spacing{
|
463 | * margin-top: 60rpx;
|
464 | * }
|
465 | * .scroll-view_H{
|
466 | * white-space: nowrap;
|
467 | * }
|
468 | * .scroll-view-item{
|
469 | * height: 300rpx;
|
470 | * }
|
471 | * .scroll-view-item_H{
|
472 | * display: inline-block;
|
473 | * width: 100%;
|
474 | * height: 300rpx;
|
475 | * }
|
476 | *
|
477 | * .demo-text-1 { background: #ccc; }
|
478 | * .demo-text-2 { background: #999; }
|
479 | * .demo-text-3 { background: #666; }
|
480 | * </style>
|
481 | * ```
|
482 | * @see https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html
|
483 | */
|
484 | declare const ScrollView: ComponentType<ScrollViewProps>
|
485 | export { ScrollView, ScrollViewProps }
|