# scroll-view

组件类型:UniScrollViewElement

可滚动视图容器

# 兼容性

Web Android iOS
4.0 3.9 4.11

# 属性

名称 类型 默认值 兼容性 描述
type string -
渲染模式,可取值 nested
合法值 兼容性 描述
nested
嵌套模式。用于处理父子 scroll-view 间的嵌套滚动,子节点只能是 nested-scroll-header nested-scroll-body 组件或自定义 refresher
direction string "vertical"
滚动方向,可取值 none、all、horizontal、vertical,默认值vertical
合法值 兼容性 描述
none
禁止滚动
all
横向竖向都可滚动 app端不支持
horizontal
横向滚动
vertical
竖向滚动
associative-container string ""
关联的滚动容器
合法值 兼容性 描述
nested-scroll-view
嵌套滚动
enable-back-to-top boolean false
iOS点击顶部状态栏滚动条返回顶部,只支持竖向
bounces boolean true
控制是否回弹效果 优先级高于rebound
upper-threshold number 50
距顶部/左边多远时(单位px),触发 scrolltoupper 事件
lower-threshold number 50
距底部/右边多远时(单位px),触发 scrolltolower 事件
scroll-top number 0
设置竖向滚动条位置
scroll-left number 0
设置横向滚动条位置
scroll-into-view string(string.IDString) -
值应为某子元素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 表示不使用默认样式
合法值 兼容性 描述
black
深颜色雪花样式
white
浅白色雪花样式
none
不使用默认样式
refresher-background string(string.ColorString) "transparent"
设置下拉刷新区域背景颜色,默认透明
refresher-triggered boolean false
设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
show-scrollbar boolean true
控制是否出现滚动条
custom-nested-scroll boolean false
子元素是否开启嵌套滚动 将滚动事件与父元素协商处理
nested-scroll-child string(string.IDString) ""
嵌套滚动子元素的id属性,不支持ref,scroll-view惯性滚动时会让对应id元素视图进行滚动,子元素滚动时会触发scroll-view的nestedprescroll事件,嵌套子元素需要设置custom-nested-scroll = true
@refresherpulling (event: UniRefresherEvent) => void -
下拉刷新控件被下拉
@refresherrefresh (event: UniRefresherEvent) => void -
下拉刷新被触发
@refresherrestore (event: UniRefresherEvent) => void -
下拉刷新被复位
@refresherabort (event: UniRefresherEvent) => void -
下拉刷新被中止
@scrolltoupper (event: UniScrollToUpperEvent) => void -
滚动到顶部/左边,会触发 scrolltoupper 事件
@scrolltolower (event: UniScrollToLowerEvent) => void -
滚动到底部/右边,会触发 scrolltolower 事件
@scroll (event: UniScrollEvent) => void -
滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}
@scrollend (event: UniScrollEvent) => void -
滚动结束时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}
@startnestedscroll (event: UniStartNestedScrollEvent) => Boolean -
子元素开始滚动时触发, return true表示与子元素开启滚动协商 默认return false! event = {node}
@nestedprescroll (event: UniNestedPreScrollEvent) => void -
子元素滚动时触发,可执行event.consumed(x,y)告知子元素deltaX、deltaY各消耗多少。子元素将执行差值后的deltaX、deltaY滚动距离。不执行consumed(x,y)则表示父元素不消耗deltaX、deltaY。event = {deltaX, deltaY}
@stopnestedscroll (event: UniStopNestedScrollEvent) => void -
子元素滚动结束或意外终止时触发
rebound boolean true
控制是否回弹效果。已废弃,请改用bounces
scroll-y boolean true
允许纵向滚动,不支持同时设置scroll-x属性为true,同时设置true时scroll-y生效。已废弃,请改用direction
scroll-x boolean false
允许横向滚动,不支持同时设置scroll-y属性为true,同时设置true时scroll-y生效。已废弃,请改用direction

# 事件

# UniRefresherEvent

# UniRefresherEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
detail UniRefresherEventDetail - - -
名称 类型 必备 默认值 兼容性 描述
dy number - - -

# UniScrollToUpperEvent

# UniScrollToUpperEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
detail UniScrollToUpperEventDetail - -
名称 类型 必备 默认值 兼容性 描述
direction string - - 滚动方向 top 或 left

# UniScrollToLowerEvent

# UniScrollToLowerEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
detail UniScrollToLowerEventDetail - -
名称 类型 必备 默认值 兼容性 描述
direction string - - 滚动方向 bottom 或 right

# UniScrollEvent

# UniScrollEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
detail UniScrollEventDetail - -
名称 类型 必备 默认值 兼容性 描述
scrollTop number - - 竖向滚动的距离
scrollLeft number - - 横向滚动的距离
scrollHeight number - - 滚动区域的高度
scrollWidth number - - 滚动区域的宽度
deltaY number - - 当次滚动事件竖向滚动量
deltaX number - - 当次滚动事件横向滚动量

# UniStartNestedScrollEvent

# UniStartNestedScrollEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
node UniElement - - 开始滚动子节点对象
isTouch boolean -
是否由触摸行为发生的Event

# UniNestedPreScrollEvent

# UniNestedPreScrollEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
deltaX number - - x轴滚动距离
deltaY number - - y轴滚动距离
isTouch boolean -
是否由触摸行为发生的Event
# UniNestedPreScrollEvent 的方法
名称 类型 必填 默认值 兼容性 描述
consumed (consumedX: number, consumedY: number) => void - - 通知到子节点x,y轴滚动距离的消耗

# UniStopNestedScrollEvent

# UniStopNestedScrollEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
isTouch boolean - - 是否由触摸行为发生的Event

# 自定义下拉刷新样式

  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>

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

# 嵌套模式

当存在两个 scroll-view 相互嵌套的场景时,两者滚动存在冲突不能很丝滑的进行衔接,可将外层 scroll-view 改成嵌套模式,这样可以让两个 scroll-view 的滚动衔接起来。

<scroll-view style="flex:1" type="nested">
	<nested-scroll-header>
		<view style="height: 200px;background-color: #66ccff;align-items: center;justify-content: center;">
			<text>nested-scroll-header</text>
		</view>
	</nested-scroll-header>
	<nested-scroll-body>
		<view style="flex:1">
			<scroll-view style="flex:1" associative-container="nested-scroll-view">
				<view v-for="index in 20" style="background-color: aliceblue; height: 80px;justify-content: center;">
					<text style="color: black;">{{index}}</text>
				</view>
			</scroll-view>
		</view>
	</nested-scroll-body>
</scroll-view>

开启嵌套模式设置如下:

  1. 设置外层 scroll-view 的 type 属性为 "nested" ,将外层 scroll-view 改成嵌套模式
  2. 设置内层 scroll-view 的 associative-container 属性为 "nested-scroll-view",开启内层 scroll-view 支持与外层 scroll-view 嵌套滚动

嵌套滚动策略:

当向下滚动(手指向上滑动)时,先滚动外层 scroll-view 再滚动内层 scroll-view;当向上滚动(手指向下滑动)时,先滚动内层 scroll-view 再滚动外层 scroll-view

注意事项:

  • 4.11版本开始支持嵌套模式
  • 外层 scroll-view 的子节点只支持nested-scroll-headernested-scroll-body和自定义 refresher
  • 外层 scroll-view 的子节点中只能有一个 nested-scroll-body
  • nested-scroll-headernested-scroll-body 只能有一个子节点
  • nested-scroll-header 只能渲染在 nested-scroll-body 上面
  • 与nested-scroll嵌套滚动协商互不兼容,nested-scroll-headernested-scroll-body优先级高于nested-scroll嵌套滚动协商
  • 内层滚动视图支持 scroll-view 和 list-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" nested-scroll-child="listview" @startnestedscroll="onStartNestedScroll" @nestedprescroll="onNestedPreScroll"
	@stopnestedscroll="onStopNestedScroll">
		...
		<view style="height: 100px;">停靠视图</view>
		<list-view id="listview"  class="child-scroll" scroll-y="true" custom-nested-scroll="true">
			...
		</list-view>
</scroll-view>
  1. 子组件准备滚动时会触发父组件的startnestedscroll事件。父组件响应startnestedscroll事件return true则表示与子组件建立嵌套滚动协商。
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)
	}
}
  1. 父组件配置nested-scroll-child后,父组件惯性滚动时会让nested-scroll-child配置的子元素进行滚动。从而触发nestedprescroll协商处理滚动事件
  2. 滚动行为停止后会触发stopnestedscroll事件

注意:

  • 仅Android平台支持嵌套滚动协商
  • 嵌套滚动协商仅支持竖向滚动,横向滚动不支持
  • nested-scroll-child设置的元素必须配置custom-nested-scroll = true,否则配置无效
  • nested-scroll-headernested-scroll-body不兼容,scroll-view 设置嵌套模式后,嵌套滚动手势协商相关事件将不会触发

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

# App平台

  • App平台scroll-x、scroll-y属性不支持同时设置为true, 同时设置true时仅scroll-y生效,4.0版本开始scroll-x、scroll-y已废弃,请使用direction属性。
  • App平台scroll-view组件不支持动态切换横竖滚动方向
  • App平台scroll-view组件的overflow属性不支持配置visible
  • App平台scroll-view组件默认高度取值:
    • scroll-view组件的子元素高度之和未超过scroll-view组件的父元素高度:
      • scroll-view组件的默认高度取值为子元素高度之和
    • scroll-view组件的子元素高度之和超过scroll-view组件的父元素高度:
      • 3.9版本scroll-view组件默认高度取值为scroll-view组件父元素的高度。子元素高度之和超过scroll-view组件的高度,scroll-view组件可滚动。
      • 4.0版本开始scroll-view组件的默认高度取值为子元素高度之和。高度相同scroll-view组件无法滚动。开发者需要设置css属性定义scroll-view组件高度,让scroll-view组件高度小于子元素高度之和,实现滚动能力。

# 示例

hello uni-app x

扫码体验(手机浏览器跳转到App直达页)

Template

Script

<template>
  <!-- #ifdef APP -->
  <scroll-view class="page-scroll-view">
  <!-- #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" direction="vertical" class="scroll-Y" scroll-with-animation="true"
            @scrolltoupper="upper" @scrolltolower="lower" @scroll="scroll" @scrollend="end"
            :show-scrollbar="showScrollbar" id="verticalScrollView">
            <view class="scroll-view-item uni-bg-red"><text class="text">A</text></view>
            <view class="scroll-view-item uni-bg-green"><text class="text">B</text></view>
            <view 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" direction="horizontal" @scroll="scroll" @scrollend="end"
            :scroll-left="scrollLeft" :show-scrollbar="showScrollbar">
            <view class="scroll-view-item_H uni-bg-red"><text class="text">A</text></view>
            <view class="scroll-view-item_H uni-bg-green"><text class="text">B</text></view>
            <view 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">
            非下拉刷新的属性示例
          </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">
            下拉刷新的属性示例
          </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"> 默认下拉刷新示例 </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">
            自定义下拉刷新示例
          </button>
        </navigator>
        <view class="uni-common-pb"></view>
      </view>
    </view>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>


<style>
  .scroll-Y {
    height: 150px;
  }

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

  .scroll-view-item {
    height: 150px;
    justify-content: center;
    align-items: center;
  }

  .scroll-view-item_H {
    width: 100%;
    height: 150px;
    justify-content: center;
    align-items: center;
  }

  .text {
    font-size: 18px;
    color: #ffffff;
  }

  .button {
    margin-top: 15px;
  }
</style>

# 参见