基础滚动组件,支持横向 和竖向滚动。当其内容区域比其本身可视区域更大时,允许用户滚动以展示更多内容。
使用指南
横向与纵向滚动
<scroll-view> 支持横向和纵向的滚动,通过 scroll-orientation 属性来实现。
<scroll-view> 固定使用 linear 布局,且布局方向由 scroll-orientation 属性决定。
滚动事件
使用 bindscroll、bindscrolltoupper / bindscrolltolower 等事件回调监听滚动进度的变化。
吸顶能力
作为 <scroll-view> 的孩子节点,可以为其设置 sticky, 使得孩子节点在滚动到距离 <scroll-view> 顶部一定位置后,不会继续跟随内容滚动,而是吸附在距离 <scroll-view> 顶部位置处。
TIP
sticky 只能被设置给 <scroll-view> 的直接子节点。Android only 上需要对 sticky 节点添加属性 flatten={false}
<scroll-view> 的直接子节点只支持 linear 与 sticky。如果需要更复杂的布局,如子节点自适应撑开,则建议给 <scroll-view> 提供一个唯一的子 view,在该唯一的子节点内部实现更健全的 CSS 能力。
<scroll-view scroll-orientation="vertical">
<view> // do any thing you want
{...}
</view>
</scroll-view>
属性
属性名和属性值用于描述元件的行为和外观
// DefaultValue: "vertical"
scroll-orientation?: string
设置 <scroll-view> 滚动方向。
| 值 | 说明 |
|---|
| vertical | <scroll-view>子节点纵向布局,<scroll-view>本身纵向滚动 |
| horizontal | <scroll-view>子节点横向布局,<scroll-view>本身横向滚动 |
// DefaultValue: true
enable-scroll?: boolean
设置是否允许手势拖拽滚动。支持动态切换,在下一次手势中生效。禁止滚动时,用户手动不能滚动
| 值 | 说明 |
|---|
| true | 用户手势可以触发滚动 |
| false | 用户手势不可以触发滚动,但仍能被 scrollTo 等滚动方法直接滚动 |
// DefaultValue: N/A
initial-scroll-offset?: number = ${number}px
设置初次渲染时的内容绝对距离偏移(与 scrollTo 方法中的 offset 概念有所区别),横纵向由 scroll-orientation 决定,仅在第一次 render 执行时起效,不响应后续更改。
TIP
与 initial-scroll-offset/to-index 会相互覆盖,不能一起使用
// DefaultValue: N/A
initial-scroll-to-index?: number = ${number}
设置初次渲染时定位到的子节点,仅在第一次 render 执行时起效,不响应后续更改。
TIP
与 initial-scroll-offset/to-index 会相互覆盖,不能一起使用
如果 index 非法(如为负值、超出子节点个数),则设置无效
bounces
// DefaultValue: true
bounces?: boolean
开启边缘回弹效果。
upper-threshold
// DefaultValue: N/A
upper-threshold?: string = ${number}px
设置一个滚动阈值 (单位 px),表示距离顶部或者左边多远时触发 scrolltoupper 事件。
lower-threshold
// DefaultValue: N/A
lower-threshold?: string = ${number}px
设置一个滚动阈值,表示距离底部或者右边多远时触发 scrolltolower 事件。
// DefaultValue: false
scroll-bar-enable?: boolean
开启滚动 条,支持动态切换。
TIP
Android only 仅纵向滚动有滚动条 iOS 支持纵向和横向滚动条
事件
前端可以在组件上绑定相应事件回调来监听组件的运行时行为。
bindscroll = (e: scrollEvent) => {};
interface scrollEvent extends CustomEvent {
detail: {
/**
* 事件名称
**/
type: 'scroll';
/**
* 距上次滚动的横向滚动偏移量
**/
deltaX: number;
/**
* 距上次滚动的纵向滚动偏移量
**/
deltaY: number;
/**
* 当前横向滚 动偏移量
**/
scrollLeft: number;
/**
* 当前纵向滚动偏移量
**/
scrollTop: number;
/**
* 当前内容区域高度
**/
scrollHeight: number;
/**
* 当前内容区域宽度
**/
scrollWidth: number;
};
}
发生滚动时(有/无动画),触发本事件。
TIP
如果有回弹 (bounces={true}),则在回弹状态下scrollLeft与scrollTop可能为负。
bindscrolltoupper = (e: scrollToUpperEvent) => {};
interface scrollToUpperEvent extends CustomEvent {
detail: {
/**
* 事件名称
**/
type: 'scrolltoupper';
/**
* 默认值
**/
deltaX: 0;
/**
* 默认值
**/
deltaY: 0;
};
}
当滚动区域的上/左边的 upperThreshold 规定的区域与可视区域相交时,触发 该事件。
bindscrolltolower = (e: scrollToLowerEvent) => {};
interface bindscrolltolower extends CustomEvent {
detail: {
/**
* 事件名称
**/
type: 'scrolltolower';
/**
* 默认值
**/
deltaX: 0;
/**
* 默认值
**/
deltaY: 0;
};
}
当滚动区域的上/左边的 lowerThreshold 规定的区域与可视区域相交时,触发该事件。
bindscrollend = (e: scrollEndEvent) => {};
interface scrollEndEvent extends CustomEvent {
detail: {
/**
* 事 件名称
**/
type: 'scrollend';
/**
* 默认值
**/
deltaX: 0;
/**
* 默认值
**/
deltaY: 0;
/**
* 当前横向滚动偏移量
**/
scrollLeft: number;
/**
* 当前纵向滚动偏移量
**/
scrollTop: number;
/**
* 当前内容区域高度
**/
scrollHeight: number;
/**
* 当前内容区域宽度
**/
scrollWidth: number;
};
}
滚动结束时触发该事件。
contentsizechanged
bindcontentsizechanged = (e: contentSizeChanged) => {};
interface contentSizeChanged extends CustomEvent {
detail: {
/**
* 事件名称
**/
type: 'contentsizechanged';
/**
* 新内容区域宽度
**/
scrollWidth: number;
/**
* 新内容区域高度
**/
scrollHeight: number;
};
}
直接子节点组成的内容区域的宽高发生变化时,触发本事件。
本事件会在 <scroll-view> 的内容完成 layout 后触发。如对 <scroll-view> 的子节点进行更新,请在该事件中调用更新后的 scrollTo 等滚动方法。
方法
前端可以通过 SelectorQuery API 执行组件的方法,使用方法如下。
index.js
lynx
.createSelectorQuery() // 创建 SelectorQuery
.select('#video') // 指定目标节点的选择器
.invoke({
// 指定对目标节点的操作
method: 'seekTo',
params: {
duration: 1000,
},
success: function (res) {
console.log(res);
},
fail: function (res) {
console.log(res.code, res.data);
},
})
.exec(); // 执行查询
<`<scroll-view>`id="scroll"/>
// 目标滚动位置的计算方法:MIN(可滚动区域,child(index).position + offset)
lynx.createSelectorQuery()
.select(`#scroll`)
.invoke({
method: 'scrollTo',
params: {
offset: 0, // offset 设置内容偏移量绝对值
index: 1, // index 目标子节点,如果设置为零,则会滚动 list 的 padding 的距离
smooth: true // smooth 设置是否平滑滚动
},
})
.exec();
将 <scroll-view> 的内容定位到特定位置,可以使用子节点序号 index 或绝对定位 offset。以 offset 为参数时,向右为正,向左为负;RTL 模式下正负会被倒转,向左为正,向右为负。
<`<scroll-view>`id="scroll"/>
lynx.createSelectorQuery()
.select(`#scroll`)
.invoke({
method: 'autoScroll',
params: {
rate: 120, // rate 滑动速度,每秒的距离(单位:px/sec)
start: true // start 设置开始或者停止自动滚动
},
})
.exec();
触发自动滚动。如果 rate 过小会无法滑动。滚动到边界后,会主动停止 autoScroll。如果用户重新反向拖拽到某一个位置,松手后, autoScroll 也不会重新触发自动滚动。
<scroll-view>
<text id="targetnode">"click me, scrollIntoView"</text>
</scroll-view>
lynx.createSelectorQuery()
.select(`#targetnode`)
.invoke({
method: 'scrollIntoView',
params: {
scrollIntoViewOptions: {
block: 'center', // 纵向对齐方式: “start" 顶对齐 | "center" 居中对齐 | "end" 底对齐
inline: 'start', // 横向对齐方式: "start" 左对齐 | "center" 居中对齐 | "end" 右对齐
behavior: 'smooth', // 'smooth', // "smooth" | "none" 可选,指顶滚动是否带有动画
},
},
})
.exec();
使 <scroll-view> 滚动到指定子节点。本方法绑定在 <scroll-view> 的任意(直接/非直接)子节点上,而不是 <scroll-view> 本身。
<`<scroll-view>`id="scrollview"/>
lynx.createSelectorQuery()
.select('#scrollview')
.invoke({
method: 'scrollBy',
params: {
offset: number, // 滚动的距离, 单位 px
},
success(res) {
console.log('succ ');
},
fail(res) {
console.log('err ');
},
}).exec();
在现有偏移量基础上滚动的距离,单位 px
性能优化建议
<scroll-view> 会一次性创建所有的子节点,这有可能导致首屏耗时非常严重。可以通过曝光事件驱动它仅创建可见的子节点。
<scroll-view> 没有任何复用机制,如果其内容过多,可能会占用非常大的问题,导致 OOM 等稳定性问题。
数据超过 3 屏时,尽可能的使用 <list> 来优化性能,或者根据曝光事件自行模拟 <VisualizedList> 逻辑。
兼容性
LCD tables only load in the browser