Skip to content

scroll-view ​

可滚动视图区域。用于区域滚动。

需注意在webview渲染的页面中,区域滚动的性能不及页面滚动。

属性说明 ​

属性名类型默认值说明平台差异说明
scroll-xBooleanfalse允许横向滚动-
scroll-yBooleanfalse允许纵向滚动-
upper-thresholdNumber/String50距顶部/左边多远时(单位px),触发 scrolltoupper 事件-
lower-thresholdNumber/String50距底部/右边多远时(单位px),触发 scrolltolower 事件-
scroll-topNumber/String-设置竖向滚动条位置-
scroll-leftNumber/String-设置横向滚动条位置-
scroll-into-viewString-值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素-
scroll-with-animationBooleanfalse在设置滚动条位置时使用动画过渡-
enable-back-to-topBooleanfalse-微信小程序
show-scrollbarBooleanfalse控制是否出现滚动条-
refresher-enabledBooleanfalse开启自定义下拉刷新H5、微信小程序基础库2.10.1+
refresher-thresholdNumber45设置自定义下拉刷新阈值H5、微信小程序基础库2.10.1+
refresher-default-styleString"black"设置自定义下拉刷新默认样式,支持设置 black,white,none,none 表示不使用默认样式H5、微信小程序基础库2.10.1+
refresher-backgroundString"#FFF"设置自定义下拉刷新区域背景颜色H5、微信小程序基础库2.10.1+
refresher-triggeredBooleanfalse设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发H5、微信小程序基础库2.10.1+
enable-flexBooleanfalse启用 flexbox 布局。开启后,当前节点声明了 display: flex 就会成为 flex container,并作用于其孩子节点。微信小程序 2.7.3
scroll-anchoringBooleanfalse开启 scroll anchoring 特性,即控制滚动位置不随内容变化而抖动,仅在 iOS 下生效,安卓下可参考 CSS overflow-anchor 属性。微信小程序 2.8.2
@scrolltoupperEventHandle-滚动到顶部/左边,会触发 scrolltoupper 事件-
@scrolltolowerEventHandle-滚动到底部/右边,会触发 scrolltolower 事件-
@scrollEventHandle-滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY} 
@refresherpullingEventHandle-自定义下拉刷新控件被下拉H5、微信小程序基础库2.10.1+
@refresherrefreshEventHandle-自定义下拉刷新被触发H5、微信小程序基础库2.10.1+
@refresherrestoreEventHandle-自定义下拉刷新被复位H5、微信小程序基础库2.10.1+
@refresherabortEventHandle-自定义下拉刷新被中止H5、微信小程序基础库2.10.1+

使用竖向滚动时,需要给 <scroll-view> 一个固定高度,通过 css 设置 height;使用横向滚动时,需要给<scroll-view>添加white-space: nowrap;样式。

示例 ​

查看演示

以下示例代码,来自于hello uni-app项目,推荐使用HBuilderX,新建uni-app项目,选择hello uni-app模板,可直接体验完整示例。

vue
<template>
  <view>
    <view class="uni-padding-wrap uni-common-mt">
    <view class="uni-title uni-common-mt">
      Vertical Scroll
      <text>\n纵向滚动</text>
    </view>
    <view>
    <scroll-view
      :scroll-top="scrollTop"
      scroll-y="true"
      class="scroll-Y"
      @scrolltoupper="upper"
      @scrolltolower="lower"
      @scroll="scroll"
    >
      <view id="demo1" class="scroll-view-item uni-bg-red">A</view>
      <view id="demo2" class="scroll-view-item uni-bg-green">B</view>
      <view id="demo3" class="scroll-view-item uni-bg-blue">C</view>
    </scroll-view>
    </view>
    <view
      @tap="goTop"
      class="uni-link uni-center uni-common-mt"
    >点击这里返回顶部</view>

    <view class="uni-title uni-common-mt">
      Horizontal Scroll
      <text>\n横向滚动</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">A</view>
        <view id="demo2" class="scroll-view-item_H uni-bg-green">B</view>
        <view id="demo3" class="scroll-view-item_H uni-bg-blue">C</view>
      </scroll-view>
    </view>
    <view class="uni-common-pb"></view>
    </view>
  </view>
</template>
<template>
  <view>
    <view class="uni-padding-wrap uni-common-mt">
    <view class="uni-title uni-common-mt">
      Vertical Scroll
      <text>\n纵向滚动</text>
    </view>
    <view>
    <scroll-view
      :scroll-top="scrollTop"
      scroll-y="true"
      class="scroll-Y"
      @scrolltoupper="upper"
      @scrolltolower="lower"
      @scroll="scroll"
    >
      <view id="demo1" class="scroll-view-item uni-bg-red">A</view>
      <view id="demo2" class="scroll-view-item uni-bg-green">B</view>
      <view id="demo3" class="scroll-view-item uni-bg-blue">C</view>
    </scroll-view>
    </view>
    <view
      @tap="goTop"
      class="uni-link uni-center uni-common-mt"
    >点击这里返回顶部</view>

    <view class="uni-title uni-common-mt">
      Horizontal Scroll
      <text>\n横向滚动</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">A</view>
        <view id="demo2" class="scroll-view-item_H uni-bg-green">B</view>
        <view id="demo3" class="scroll-view-item_H uni-bg-blue">C</view>
      </scroll-view>
    </view>
    <view class="uni-common-pb"></view>
    </view>
  </view>
</template>
js
<script>
export default {
  data() {
    return {
      scrollTop: 0,
      old: {
        scrollTop: 0,
      },
    };
  },
  methods: {
    upper: function(e) {
      console.log(e)
    },
    lower: function(e) {
      console.log(e)
    },
    scroll: function(e) {
      console.log(e)
      this.old.scrollTop = e.detail.scrollTop
    },
    goTop: function(e) {
      // 解决view层不同步的问题
      this.scrollTop = this.old.scrollTop
      this.$nextTick(function() {
        this.scrollTop = 0
        });
      qin.showToast({
        icon: "none",
        title: "纵向滚动 scrollTop 值已被修改为 0",
      });
    },
  },
};
</script>
<script>
export default {
  data() {
    return {
      scrollTop: 0,
      old: {
        scrollTop: 0,
      },
    };
  },
  methods: {
    upper: function(e) {
      console.log(e)
    },
    lower: function(e) {
      console.log(e)
    },
    scroll: function(e) {
      console.log(e)
      this.old.scrollTop = e.detail.scrollTop
    },
    goTop: function(e) {
      // 解决view层不同步的问题
      this.scrollTop = this.old.scrollTop
      this.$nextTick(function() {
        this.scrollTop = 0
        });
      qin.showToast({
        icon: "none",
        title: "纵向滚动 scrollTop 值已被修改为 0",
      });
    },
  },
};
</script>
css
<style>
  .scroll-Y {
    height: 300rpx;
  }
  .scroll-view_H {
    white-space: nowrap;
    width: 100%;
  }
  .scroll-view-item {
    height: 300rpx;
    line-height: 300rpx;
    text-align: center;
    font-size: 36rpx;
  }
  .scroll-view-item_H {
    display: inline-block;
    width: 100%;
    height: 300rpx;
    line-height: 300rpx;
    text-align: center;
    font-size: 36rpx;
  }
</style>
<style>
  .scroll-Y {
    height: 300rpx;
  }
  .scroll-view_H {
    white-space: nowrap;
    width: 100%;
  }
  .scroll-view-item {
    height: 300rpx;
    line-height: 300rpx;
    text-align: center;
    font-size: 36rpx;
  }
  .scroll-view-item_H {
    display: inline-block;
    width: 100%;
    height: 300rpx;
    line-height: 300rpx;
    text-align: center;
    font-size: 36rpx;
  }
</style>

自定义下拉刷新 ​

注意,在webview渲染时,自定义下拉刷新的性能不及pages.json中配置的原生下拉刷新。

vue
<template>
  <view>
    <scroll-view
      style="height:
      300px;"
      scroll-y="true"
      refresher-enabled="true"
      :refresher-triggered="triggered"
      :refresher-threshold="100"
      refresher-background="lightgreen"
      @refresherpulling="onPulling"
      @refresherrefresh="onRefresh"
      @refresherrestore="onRestore"
      @refresherabort="onAbort"
    />
  </view>
</template>
<template>
  <view>
    <scroll-view
      style="height:
      300px;"
      scroll-y="true"
      refresher-enabled="true"
      :refresher-triggered="triggered"
      :refresher-threshold="100"
      refresher-background="lightgreen"
      @refresherpulling="onPulling"
      @refresherrefresh="onRefresh"
      @refresherrestore="onRestore"
      @refresherabort="onAbort"
    />
  </view>
</template>
js
<script>
  export default {
    data() {
      return {
        triggered: false,
      }
    },
    onLoad() {
      this._freshing = false;
      setTimeout(() => {
        this.triggered = true;
      }, 1000)
    },
    methods: {
      onPulling(e) {
        console.log("onpulling", e);
      },
      onRefresh() {
        if (this._freshing) return;
        this._freshing = true;
        setTimeout(() => {
          this.triggered = false;
          this._freshing = false;
        }, 3000)
      },
      onRestore() {
        this.triggered = 'restore'; // 需要重置
        console.log("onRestore");
      },
      onAbort() {
        console.log("onAbort");
      }
    }
  }
</script>
<script>
  export default {
    data() {
      return {
        triggered: false,
      }
    },
    onLoad() {
      this._freshing = false;
      setTimeout(() => {
        this.triggered = true;
      }, 1000)
    },
    methods: {
      onPulling(e) {
        console.log("onpulling", e);
      },
      onRefresh() {
        if (this._freshing) return;
        this._freshing = true;
        setTimeout(() => {
          this.triggered = false;
          this._freshing = false;
        }, 3000)
      },
      onRestore() {
        this.triggered = 'restore'; // 需要重置
        console.log("onRestore");
      },
      onAbort() {
        console.log("onAbort");
      }
    }
  }
</script>

webview中使用scroll-view的注意@webviewtips ​

  • 原生组件嵌套问题
  • 微信基础库 2.4.4 起支持了原生组件在 scroll-view 、 swiper 、 movable-view 中的使用。但并非所有小程序都支持,需具体查询各家小程序 webview 是否实现了同层渲染。
  • 长列表性能问题
  • scroll-view 不适合放长列表,有性能问题。webview渲染时,建议改用webview的页面滚动。
  • 如果您一定要在 webview 中实现区域长列表,建议使用三方如better-scroll组件,或者插件市场搜索 虚拟列表,这些专业组件实现了 dom 复用,即便列表很长也不会创建很多dom。
  • 下拉刷新问题
  • webview渲染时,建议使用页面级的原生下拉刷新,性能更好。如一定要在webview中自定义下拉刷新,建议插件市场搜索虚拟列表,这些专业组件使用 wxs 、 renderjs 等技术避免通信阻塞。
  • scroll-view 是区域滚动,不会触发页面滚动,无法触发 pages.json 配置的下拉刷新、页面触底 onReachBottomDistance 的 transparent 透明渐变。
  • webview渲染时,scroll-view 的滚动条设置,可通过 css 的 -webkit-scrollbar 自定义,包括隐藏滚动条。

其他注意事项 ​