# scroll-view

可滚动视图容器

# # 属性

名称 类型 默认值 描述
scroll-x boolean false 允许横向滚动,不支持同时设置scroll-y属性为true,同时设置true时scroll-y生效
scroll-y boolean true 允许纵向滚动,不支持同时设置scroll-x属性为true,同时设置true时scroll-y生效
rebound boolean true 控制是否回弹效果
upper-threshold number 50 距顶部/左边多远时(单位px),触发 scrolltoupper 事件
lower-threshold number 50 距底部/右边多远时(单位px),触发 scrolltolower 事件
scroll-top number 0 设置竖向滚动条位置
scroll-left number 0 设置横向滚动条位置
scroll-into-view string - 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素
scroll-with-animation boolean false 是否在设置滚动条位置时使用滚动动画,设置false没有滚动动画
refresher-enabled boolean false 开启下拉刷新,暂时不支持scroll-x = true横向刷新
refresher-threshold number 45 设置下拉刷新阈值
refresher-max-drag-distance number - 设置下拉最大拖拽距离(单位px),默认是下拉刷新控件高度的2.5倍
refresher-default-style string black 设置下拉刷新默认样式,支持设置 black | white | none, none 表示不使用默认样式 refresher-default-style
refresher-background string #FFF 设置下拉刷新区域背景颜色
refresher-triggered boolean false 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
show-scrollbar boolean true 控制是否出现滚动条
custom-nested-scroll boolean false 子元素是否开启嵌套滚动 将滚动事件与父元素协商处理
@refresherpulling (event: RefresherEvent) => void - 下拉刷新控件被下拉
@refresherrefresh (event: RefresherEvent) => void - 下拉刷新被触发
@refresherrestore (event: RefresherEvent) => void - 下拉刷新被复位
@refresherabort (event: RefresherEvent) => void - 下拉刷新被中止
@scrolltoupper (event: ScrollToUpperEvent) => void - 滚动到顶部/左边,会触发 scrolltoupper 事件
@scrolltolower (event: ScrollToLowerEvent) => void - 滚动到底部/右边,会触发 scrolltolower 事件
@scroll (event: ScrollEvent) => void - 滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}
@startnestedscroll (event: StartNestedScrollEvent) => Boolean - 子元素开始滚动时触发, return ture表示与子元素开启滚动协商 默认return false! event = {node}
@nestedprescroll (event: NestedPreScrollEvent) => void - 子元素滚动时触发,可执行event.consumed(x,y)告知子元素deltaX、deltaY各消耗多少。子元素将执行差值后的deltaX、deltaY滚动距离。不执行consumed(x,y)则表示父元素不消耗deltaX、deltaY。event = {deltaX, deltaY}
@stopnestedscroll (event: Event) => void - 子元素滚动结束或意外终止时触发

# # refresher-default-style

值名称 描述
black 深颜色雪花样式
white 浅白色雪花样式
none 不使用默认样式
# # refresher-default-style 兼容性
安卓系统版本 安卓 uni-app 安卓 uni-app-x iOS 系统版本 iOS uni-app iOS uni-app-x
black 5.0 x 3.9+ - - -
white 5.0 x 3.9+ - - -
none 5.0 x 3.9+ - - -

# # 事件

# # RefresherEvent

# # RefresherEvent 属性值
名称 类型 必填 默认值 描述
detail RefresherEventDetail - -
type string - 事件类型
target Element - 触发事件的组件
currentTarget Element - 当前组件
timeStamp number - 事件发生时的时间戳
# # RefresherEventDetail 属性值
名称 类型 必备 默认值 描述
dy number - -
# # RefresherEvent 方法
名称 类型 必填 默认值 描述
stopPropagation () => void - 阻止当前事件的进一步传播
preventDefault () => void - 阻止当前事件的默认行为

# # ScrollToUpperEvent

# # ScrollToUpperEvent 属性值
名称 类型 必填 默认值 描述
detail ScrollToUpperEventDetail - -
type string - 事件类型
target Element - 触发事件的组件
currentTarget Element - 当前组件
timeStamp number - 事件发生时的时间戳
# # ScrollToUpperEventDetail 属性值
名称 类型 必备 默认值 描述
direction string - 滚动方向 top 或 left
# # ScrollToUpperEvent 方法
名称 类型 必填 默认值 描述
stopPropagation () => void - 阻止当前事件的进一步传播
preventDefault () => void - 阻止当前事件的默认行为

# # ScrollToLowerEvent

# # ScrollToLowerEvent 属性值
名称 类型 必填 默认值 描述
detail ScrollToLowerEventDetail - -
type string - 事件类型
target Element - 触发事件的组件
currentTarget Element - 当前组件
timeStamp number - 事件发生时的时间戳
# # ScrollToLowerEventDetail 属性值
名称 类型 必备 默认值 描述
direction string - 滚动方向 bottom 或 right
# # ScrollToLowerEvent 方法
名称 类型 必填 默认值 描述
stopPropagation () => void - 阻止当前事件的进一步传播
preventDefault () => void - 阻止当前事件的默认行为

# # ScrollEvent

# # ScrollEvent 属性值
名称 类型 必填 默认值 描述
detail ScrollEventDetail - -
type string - 事件类型
target Element - 触发事件的组件
currentTarget Element - 当前组件
timeStamp number - 事件发生时的时间戳
# # ScrollEventDetail 属性值
名称 类型 必备 默认值 描述
scrollTop number - 竖向滚动的距离
scrollLeft number - 横向滚动的距离
scrollHeight number - 滚动区域的高度
scrollWidth number - 滚动区域的宽度
deltaY number - 当次滚动事件竖向滚动量
deltaX number - 当次滚动事件横向滚动量
# # ScrollEvent 方法
名称 类型 必填 默认值 描述
stopPropagation () => void - 阻止当前事件的进一步传播
preventDefault () => void - 阻止当前事件的默认行为

# # StartNestedScrollEvent

# # StartNestedScrollEvent 属性值
名称 类型 必填 默认值 描述
node Element - 开始滚动子节点对象
type string - 事件类型
target Element - 触发事件的组件
currentTarget Element - 当前组件
timeStamp number - 事件发生时的时间戳
# # StartNestedScrollEvent 方法
名称 类型 必填 默认值 描述
stopPropagation () => void - 阻止当前事件的进一步传播
preventDefault () => void - 阻止当前事件的默认行为

# # NestedPreScrollEvent

# # NestedPreScrollEvent 属性值
名称 类型 必填 默认值 描述
deltaX number - x轴滚动距离
deltaY number - y轴滚动距离
type string - 事件类型
target Element - 触发事件的组件
currentTarget Element - 当前组件
timeStamp number - 事件发生时的时间戳
# # NestedPreScrollEvent 方法
名称 类型 必填 默认值 描述
consumed (consumedX: number, consumedY: number) => void - 通知到子节点x,y轴滚动距离的消耗
stopPropagation () => void - 阻止当前事件的进一步传播
preventDefault () => void - 阻止当前事件的默认行为

# # 示例

hello uni-app x

<template>
   <!-- #ifdef APP -->
   <scroll-view style="flex: 1">
   	<!-- #endif -->
   	<view>
   		<page-head title="scroll-view,区域滚动视图"></page-head>
   		<view class="uni-padding-wrap uni-common-mt">
   			<view class="uni-title uni-common-mt">
   				<text class="uni-title-text">Vertical Scroll</text>
   				<text class="uni-subtitle-text">纵向滚动</text>
   			</view>
   			<view>
   				<scroll-view :scroll-top="scrollTop" :scroll-y="true" class="scroll-Y" scroll-with-animation="true"
   					@scrolltoupper="upper" @scrolltolower="lower" @scroll="scroll">
   					<view id="demo1" class="scroll-view-item uni-bg-red"><text class="text">A</text></view>
   					<view id="demo2" class="scroll-view-item uni-bg-green"><text class="text">B</text></view>
   					<view id="demo3" class="scroll-view-item uni-bg-blue"><text class="text">C</text></view>
   				</scroll-view>
   			</view>
   			<view @tap="goTop" class="uni-center uni-common-mt">
   				<text class="uni-link">点击这里返回顶部</text>
   			</view>

   			<view class="uni-title uni-common-mt">
   				<text class="uni-title-text">Horizontal Scroll</text>
   				<text class="uni-subtitle-text">横向滚动</text>
   			</view>
   			<view>
   				<scroll-view class="scroll-view_H" :scroll-x="true" @scroll="scroll" :scroll-left="120">
   					<view id="demo1" class="scroll-view-item_H uni-bg-red"><text class="text">A</text></view>
   					<view id="demo2" class="scroll-view-item_H uni-bg-green"><text class="text">B</text></view>
   					<view id="demo3" class="scroll-view-item_H uni-bg-blue"><text class="text">C</text></view>
   				</scroll-view>
   			</view>

   			<navigator url="/pages/component/scroll-view/scroll-view-props" hover-class="none">
   			<button type="primary" class="button default-button">
   				非下拉刷新的属性示例
   			</button>
   			</navigator>
   			<view class="uni-common-pb"></view>
   			<navigator url="/pages/component/scroll-view/scroll-view-refresher-props" hover-class="none">
   			<button type="primary" class="button default-button">
   				下拉刷新的属性示例
   			</button>
   			</navigator>
   			<view class="uni-common-pb"></view>
   			<navigator url="/pages/component/scroll-view/scroll-view-refresher" hover-class="none">
   			<button type="primary" class="button default-button"> 默认下拉刷新示例 </button>
   			</navigator>
   			<view class="uni-common-pb"></view>
   			<navigator url="/pages/component/scroll-view/scroll-view-custom-refresher-props" hover-class="none">
   			<button type="primary" class="button default-button">
   				自定义下拉刷新示例
   			</button>
   			</navigator>
   			<view class="uni-common-pb"></view>
   		</view>
   	</view>
   	<!-- #ifdef APP -->
   </scroll-view>
   <!-- #endif -->
</template>
<script lang="uts">
   export default {
   	data() {
   		return {
   			scrollTop: 0,
   			oldScrollTop: 0,
   		}
   	},
   	methods: {
   		upper: function (e : ScrollToUpperEvent) {
   			console.log(e)
   		},
   		lower: function (e : ScrollToLowerEvent) {
   			console.log(e)
   		},
   		scroll: function (e : ScrollEvent) {
   			this.oldScrollTop = e.detail.scrollTop
   		},
   		goTop: function () {
   			// 解决view层不同步的问题
   			this.scrollTop = this.oldScrollTop
   			this.$nextTick(function () {
   				this.scrollTop = 0
   			})
   			uni.showToast({
   				icon: 'none',
   				title: '纵向滚动 scrollTop 值已被修改为 0',
   			})
   		}
   	},
   }
</script>

<style>
   .scroll-Y {
   	height: 300rpx;
   }

   .scroll-view_H {
   	width: 100%;
   	flex-direction: row;
   }

   .scroll-view-item {
   	height: 300rpx;
   	justify-content: center;
   	align-items: center;
   }

   .scroll-view-item_H {
   	width: 690rpx;
   	height: 300rpx;
   	justify-content: center;
   	align-items: center;
   }

   .text {
   	font-size: 36rpx;
   	color: #ffffff;
   }

   .button {
   	margin-top: 30rpx;
   }
</style>

# 自定义下拉刷新样式

  1. 设置refresher-default-style属性为 none 不使用默认样式
  2. 自定义下拉刷新元素必须要声明为 slot="refresher",需要设置刷新元素宽高信息否则可能无法正常显示!
  3. 通过组件提供的refresherpulling、refresherrefresh、refresherrestore、refresherabort下拉刷新事件调整自定义下拉刷新元素!实现预期效果

注意: 目前自定义下拉刷新元素不支持放在scroll-view的首个子元素位置上。可能无法正常显示

<scroll-view refresher-default-style="none" :refresher-enabled="true" :refresher-triggered="refresherTriggered"
			 @refresherpulling="onRefresherpulling" @refresherrefresh="onRefresherrefresh" 
			 @refresherrestore="onRefresherrestore" style="flex:1" >
			 
		<view v-for="i in 20" class="content-item">
			<text class="text">item-{{i}}</text>
		</view>
		
		<!-- 自定义下拉刷新元素 -->
		<view slot="refresher" class="refresh-box">
			<text class="tip-text">{{text[state]}}</text>
		</view>
		
</scroll-view>

具体代码请参考:自定义下拉刷新样式示例

# nested-scroll嵌套滚动协商

嵌套滚动是原生才有的概念,web没有。

它是指父子2个滚动容器嵌套,在滚动时可以互相协商,控制父容器怎么滚、子容器怎么滚。

  1. 通过在子滚动容器设置custom-nested-scroll = true,开启与父组件实现嵌套滚动协商。仅list-view、scroll-view组件支持与父组件嵌套滚动协商。

下面的示例代码,在一个scroll-view中嵌套了一个list-view。在list-view上设置了custom-nested-scroll="true"。

<scroll-view style="height: 100%;" scroll-y="true" rebound ="false" @startnestedscroll="onStartNestedScroll" @nestedprescroll="onNestedPreScroll"
	@stopnestedscroll="onStopNestedScroll">
		...
		<view style="height: 100px;">停靠视图</view>
		<list-view class="child-scroll" scroll-y="true" custom-nested-scroll="true">
			...
		</list-view>
</scroll-view>
  1. 子组件准备滚动时会触发父组件的startnestedscroll事件。父组件响应startnestedscroll事件return ture则表示与子组件建立嵌套滚动协商。
onStartNestedScroll(event: StartNestedScrollEvent): Boolean {
	//开启与子组件建立嵌套滚动协商
	return true
}
  1. 当建立嵌套滚动协商后,子组件滚动时父组件会持续收到nestedprescroll事件,这个事件的含义是嵌套滚动即将发生。 事件中会返回NestedPreScrollEvent子组件将要滚动的数据。
  2. 父组件执行NestedPreScrollEvent.consumed(x,y)函数,告知子组件本次nestedprescroll事件deltaX、deltaY各消耗多少,即父组件要消费掉多少滚动距离。 子组件将执行差值后的deltaX、deltaY滚动距离,也就是剩余的滚动余量留给子组件。
onNestedPreScroll(event: NestedPreScrollEvent) {
	var deltaY = event.deltaY
	var deltaX = event.deltaX
	...
	if() {
		//告知子组件deltaX、deltaY各消耗多少
		event.consumed(x, y)
	}
}
  • 滚动行为停止后会触发stopnestedscroll事件
  • 仅Android平台支持嵌套滚动协商

具体代码请参考:nested-scroll嵌套滚动示例

# # 兼容性

安卓系统版本 安卓 uni-app 安卓 uni-app-x iOS 系统版本 iOS uni-app iOS uni-app-x
scroll-view 5.0 3.9+ 9.0 -
scroll-x 5.0 3.9+ - - -
scroll-y 5.0 3.9+ - - -
rebound 5.0 x 3.9+ - - -
upper-threshold 5.0 3.9+ - - -
lower-threshold 5.0 3.9+ - - -
scroll-top 5.0 3.9+ - - -
scroll-left 5.0 3.9+ - - -
scroll-into-view 5.0 3.9+ - - -
scroll-with-animation 5.0 3.9+ - - -
refresher-enabled 5.0 3.9+ - - -
refresher-threshold 5.0 3.9+ - - -
refresher-max-drag-distance 5.0 x 3.9+ - - -
refresher-default-style 5.0 3.9+ - - -
refresher-background 5.0 3.9+ - - -
refresher-triggered 5.0 3.9+ - - -
show-scrollbar 5.0 3.9+ - - -
custom-nested-scroll 5.0 x 3.9+ 9.0 -
@refresherpulling 5.0 3.9+ 9.0 -
@refresherrefresh 5.0 3.9+ 9.0 -
@refresherrestore 5.0 3.9+ 9.0 -
@refresherabort 5.0 3.9+ 9.0 -
@scrolltoupper 5.0 3.9+ 9.0 -
@scrolltolower 5.0 3.9+ 9.0 -
@scroll 5.0 3.9+ 9.0 -
@startnestedscroll 5.0 x 3.9+ 9.0 x -
@nestedprescroll 5.0 x 3.9+ 9.0 x -
@stopnestedscroll 5.0 x 3.9+ 9.0 x -

# # 参见