# scroll-view

> 基础库 1.0.0 开始支持，低版本需做[兼容处理](1003706)。

> __微信 Windows 版__：支持
> 
> __微信 Mac 版__：支持
> 
> __微信 鸿蒙 OS 版__：支持

> 相关文档: [Skyline 渲染引擎](/miniprogram/dev/framework/runtime/skyline/introduction.md)、[Skyline 迁移起步](/miniprogram/dev/framework/custom-component/glass-easel/migration.md)

渲染框架支持情况：Skyline （使用最新 [Nightly](/miniprogram/dev/devtools/nightly.html) 工具调试）、WebView

## 功能描述

可滚动视图区域。使用竖向滚动时，需要给[scroll-view](/miniprogram/dev/component/view-component/scroll-view)一个固定高度，通过 WXSS 设置 height。组件属性的长度单位默认为px，[2.4.0](1003706)起支持传入单位(rpx/px)。

1. 横向滚动需打开 enable-flex 以兼容 WebView，如 <scroll-view scroll-x enable-flex style="flex-direction: row;"/> 

2. 滚动条的长度是预估的，若直接子节点的高度差别较大，则滚动条长度可能会不准确
3. 使用 `worklet` 函数需要开启开发者工具 "将 JS 编译成 ES5" 或 "编译 worklet 函数" 选项。

## 通用属性


```json
[
  {
    "属性": "scroll-x",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "允许横向滚动",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "scroll-y",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "允许纵向滚动",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "upper-threshold",
    "类型": "number/string",
    "默认值": "50",
    "必填": "否",
    "说明": "距顶部/左边多远时，触发 scrolltoupper 事件",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "lower-threshold",
    "类型": "number/string",
    "默认值": "50",
    "必填": "否",
    "说明": "距底部/右边多远时，触发 scrolltolower 事件",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "scroll-top",
    "类型": "number/string",
    "默认值": "",
    "必填": "否",
    "说明": "设置竖向滚动条位置",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "scroll-left",
    "类型": "number/string",
    "默认值": "",
    "必填": "否",
    "说明": "设置横向滚动条位置",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "scroll-into-view",
    "类型": "string",
    "默认值": "",
    "必填": "否",
    "说明": "值应为某子元素id（id不能以数字开头）。设置哪个方向可滚动，则在哪个方向滚动到该元素",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "scroll-into-view-offset",
    "类型": "number",
    "默认值": "0",
    "必填": "否",
    "说明": "跳转到 scroll-into-view 目标节点时的额外偏移。skyline 自 3.1.0 版本开始支持，webview 自 3.6.0 版本开始支持。",
    "最低版本": "[3.1.0](1003706)"
  },
  {
    "属性": "scroll-with-animation",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "在设置滚动条位置时使用动画过渡",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "enable-back-to-top",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "iOS点击顶部状态栏、安卓双击标题栏时，滚动条返回顶部，只支持竖向。自 2.27.3 版本开始，若非显式设置为 false，则在显示尺寸大于屏幕 90% 时自动开启。鸿蒙 OS 暂不支持",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "enable-passive",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "开启 passive 特性，能优化一定的滚动性能",
    "最低版本": "[2.25.3](1003706)"
  },
  {
    "属性": "refresher-enabled",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "开启自定义下拉刷新",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "refresher-threshold",
    "类型": "number",
    "默认值": "45",
    "必填": "否",
    "说明": "设置自定义下拉刷新阈值",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "refresher-default-style",
    "类型": "string",
    "默认值": "\"black\"",
    "必填": "否",
    "说明": "设置自定义下拉刷新默认样式，支持设置 \u0000INLINECODE_1\u0000， none 表示不使用默认样式",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "refresher-background",
    "类型": "string",
    "默认值": "",
    "必填": "否",
    "说明": "设置自定义下拉刷新区域背景颜色，默认为透明",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "refresher-triggered",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "设置当前下拉刷新状态，true 表示下拉刷新已经被触发，false 表示下拉刷新未被触发",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "bounces",
    "类型": "boolean",
    "默认值": "true",
    "必填": "否",
    "说明": "iOS 下 scroll-view 边界弹性控制 (同时开启 enhanced 属性后生效)",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "show-scrollbar",
    "类型": "boolean",
    "默认值": "true",
    "必填": "否",
    "说明": "滚动条显隐控制，仅对垂直滚动条有效 (同时开启 enhanced 属性后生效)",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "fast-deceleration",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "滑动减速速率控制, 仅在 iOS 下生效 (同时开启 enhanced 属性后生效)",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "bind:dragstart",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滑动开始事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft }",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "bind:dragging",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滑动事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft }",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "bind:dragend",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滑动结束事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft, velocity }",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "bind:scrolltoupper",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滚动到顶部/左边时触发",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "bind:scrolltolower",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滚动到底部/右边时触发",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "bind:scroll",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滚动时触发，event.detail = { scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY }。skyline 从 3.6.6开始，额外具有 boundaryVelocity 字段：如果该次滚动会触碰到边界，从该次滚动触发起到下一个滚动事件发生或者当次滚动事件结束为止 boundaryVelocity 将被置为触碰边界时的速度，否则置为 NAN。",
    "最低版本": "[1.0.0](1003706)"
  },
  {
    "属性": "bind:refresherpulling",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "自定义下拉刷新控件被下拉",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "bind:refresherrefresh",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "自定义下拉刷新被触发",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "bind:refresherrestore",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "自定义下拉刷新被复位",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "bind:refresherabort",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "自定义下拉刷新被中止",
    "最低版本": "[2.10.1](1003706)"
  },
  {
    "属性": "scroll-anchoring",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "开启 scroll anchoring 特性，即控制滚动位置不随内容变化而抖动，可参考 CSS \u0000INLINECODE_2\u0000 属性。webview 仅在 iOS 下生效。skyline 自 3.6.2 版本开始支持，默认为 true 。",
    "最低版本": "[2.8.2](1003706)"
  }
]
```

## Skyline 特有属性


```json
[
  {
    "属性": "type",
    "类型": "string",
    "默认值": "",
    "必填": "否",
    "说明": "渲染模式",
    "最低版本": "",
    "子项": [
      {
        "合法值": "list",
        "说明": "列表模式。只会渲染在屏节点，会根据直接子节点是否在屏来按需渲染，若只有一个直接子节点则性能会退化",
        "最低版本": "[2.25.2](1003706)"
      },
      {
        "合法值": "custom",
        "说明": "自定义模式。只会渲染在屏节点，子节点可以是 [sticky-section](/miniprogram/dev/component/skyline/sticky-section) [list-view](/miniprogram/dev/component/skyline/list-view) [grid-view](/miniprogram/dev/component/skyline/grid-view) 等组件",
        "最低版本": "[2.29.0](1003706)"
      },
      {
        "合法值": "nested",
        "说明": "嵌套模式。用于处理父子 scroll-view 间的嵌套滚动，子节点可以是 [nested-scroll-header](/miniprogram/dev/component/skyline/nested-scroll-header) [nested-scroll-body](/miniprogram/dev/component/skyline/nested-scroll-body) 组件或自定义 refresher",
        "最低版本": "[3.2.0](1003706)"
      }
    ]
  },
  {
    "属性": "associative-container",
    "类型": "string",
    "默认值": "",
    "必填": "否",
    "说明": "关联的滚动容器",
    "最低版本": "[3.2.0](1003706)",
    "子项": [
      {
        "合法值": "draggable-sheet",
        "说明": "关联 [draggable-sheet](/miniprogram/dev/component/skyline/draggable-sheet) 组件",
        "最低版本": "[3.2.0](1003706)"
      },
      {
        "合法值": "nested-scroll-view",
        "说明": "关联 \u0000INLINECODE_3\u0000 嵌套模式",
        "最低版本": "[3.2.0](1003706)"
      },
      {
        "合法值": "pop-gesture",
        "说明": "关联 [页面手势返回](/miniprogram/dev/framework/runtime/skyline/pop-gesture.md)",
        "最低版本": "[3.4.0](1003706)"
      }
    ]
  },
  {
    "属性": "reverse",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "是否反向滚动。一般初始滚动位置是在顶部，反向滚动则是在底部。",
    "最低版本": "[2.27.2](1003706)"
  },
  {
    "属性": "clip",
    "类型": "boolean",
    "默认值": "true",
    "必填": "否",
    "说明": "是否对溢出进行裁剪，默认开启",
    "最低版本": "[2.32.1](1003706)"
  },
  {
    "属性": "enable-back-to-top",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "仅 iOS 支持，其余同 WebView 同名组件",
    "最低版本": "[2.32.1](1003706)"
  },
  {
    "属性": "cache-extent",
    "类型": "number",
    "默认值": "",
    "必填": "否",
    "说明": "指定视口外渲染区域的距离，默认情况下视口外节点不渲染。指定 cache-extent 可优化滚动体验和加载速度，但会提高内存占用且影响首屏速度，可按需启用。",
    "最低版本": "[2.29.0](1003706)"
  },
  {
    "属性": "min-drag-distance",
    "类型": "number",
    "默认值": "18",
    "必填": "否",
    "说明": "指定 scroll-view 触发滚动的最小拖动距离。仅在 scroll-view 和其他组件存在手势冲突时使用，可通过调整该属性使得滚动更加灵敏。",
    "最低版本": "[2.33.0](1003706)"
  },
  {
    "属性": "scroll-into-view-within-extent",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "只 scroll-into-view 到 cacheExtent 以内的目标节点，性能更佳",
    "最低版本": "[2.29.0](1003706)"
  },
  {
    "属性": "scroll-into-view-alignment",
    "类型": "string",
    "默认值": "start",
    "必填": "否",
    "说明": "指定 scroll-into-view 目标节点在视口内的位置",
    "最低版本": "[2.29.0](1003706)",
    "子项": [
      {
        "合法值": "start",
        "说明": "目标节点显示在视口开始处"
      },
      {
        "合法值": "center",
        "说明": "目标节点显示在视口中间"
      },
      {
        "合法值": "end",
        "说明": "目标节点显示在视口结束处"
      },
      {
        "合法值": "nearest",
        "说明": "目标节点在就近的视口边缘显示，若节点已在视口内则不触发滚动"
      }
    ]
  },
  {
    "属性": "bind:scrollstart",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滚动开始事件，仅支持非 worklet 的组件方法作为回调。event.detail = { isDrag }",
    "最低版本": "[2.29.0](1003706)"
  },
  {
    "属性": "bind:scroll",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滚动事件，多返回 isDrag 字段，仅支持非 worklet 的组件方法作为回调。event.detail = { isDrag }",
    "最低版本": ""
  },
  {
    "属性": "bind:scrollend",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "滚动结束事件，仅支持非 worklet 的组件方法作为回调。event.detail = { isDrag }",
    "最低版本": "[2.29.0](1003706)"
  },
  {
    "属性": "worklet:onscrollstart",
    "类型": "worklet",
    "默认值": "",
    "必填": "否",
    "说明": "同 \u0000INLINECODE_4\u0000，但仅支持 worklet 作为回调",
    "最低版本": "[2.29.2](1003706)"
  },
  {
    "属性": "worklet:onscrollupdate",
    "类型": "worklet",
    "默认值": "",
    "必填": "否",
    "说明": "\u0000INLINECODE_5\u0000 ，但仅支持 worklet 作为回调",
    "最低版本": "[2.29.2](1003706)"
  },
  {
    "属性": "worklet:onscrollend",
    "类型": "worklet",
    "默认值": "",
    "必填": "否",
    "说明": "同 \u0000INLINECODE_6\u0000，但仅支持 worklet 作为回调",
    "最低版本": "[2.29.2](1003706)"
  },
  {
    "属性": "bind:refresherwillrefresh",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "自定义下拉刷新即将触发刷新（拖动超过 refresher-threshold 时）的事件",
    "最低版本": "[2.29.0](1003706)"
  },
  {
    "属性": "worklet:adjust-deceleration-velocity",
    "类型": "callback",
    "默认值": "",
    "必填": "否",
    "说明": "指定手指抬起时做惯性滚动的初速度。(velocity: number) => number",
    "最低版本": "[2.29.2](1003706)"
  },
  {
    "属性": "padding",
    "类型": "Array",
    "默认值": "[0, 0, 0, 0]",
    "必填": "否",
    "说明": "长度为 4 的数组，按 top、right、bottom、left 顺序指定内边距",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "refresher-two-level-enabled",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "开启下拉二级能力",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "refresher-two-level-triggered",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "设置打开/关闭二级",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "refresher-two-level-threshold",
    "类型": "number",
    "默认值": "150",
    "必填": "否",
    "说明": "下拉二级阈值",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "refresher-two-level-close-threshold",
    "类型": "number",
    "默认值": "80",
    "必填": "否",
    "说明": "滑动返回时关闭二级的阈值",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "refresher-two-level-scroll-enabled",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "处于二级状态时是否可滑动",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "refresher-ballistic-refresh-enabled",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "惯性滚动是否触发下拉刷新",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "refresher-two-level-pinned",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "即将打开二级时否定住",
    "最低版本": "[3.0.0](1003706)"
  },
  {
    "属性": "bind:refresherstatuschange",
    "类型": "eventhandle",
    "默认值": "",
    "必填": "否",
    "说明": "下拉刷新状态回调",
    "最低版本": "[3.0.0](1003706)"
  }
]
```

## WebView 特有属性


```json
[
  {
    "属性": "enable-flex",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "启用 flexbox 布局。开启后，当前节点声明了 \u0000INLINECODE_7\u0000 就会成为 flex container，并作用于其孩子节点。",
    "最低版本": "[2.7.3](1003706)"
  },
  {
    "属性": "enhanced",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "启用 scroll-view 增强特性，启用后可通过 [ScrollViewContext](/miniprogram/dev/api/ui/scroll/ScrollViewContext.md) 操作 scroll-view。鸿蒙 OS 暂不支持 enhanced 及其相关的属性和方法。",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "paging-enabled",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "分页滑动效果 (同时开启 enhanced 属性后生效)",
    "最低版本": "[2.12.0](1003706)"
  },
  {
    "属性": "using-sticky",
    "类型": "boolean",
    "默认值": "false",
    "必填": "否",
    "说明": "使 scroll-view 下的 position sticky 特性生效，否则滚动一屏后 sticky 元素会被隐藏",
    "最低版本": "[3.2.1](1003706)"
  }
]
```

## Bug & Tip

1. `tip`: 基础库 [2.4.0](1003706)以下不支持嵌套`textarea`、`map`、`canvas`、`video` 组件
1. `tip`: `scroll-into-view` 的优先级高于 `scroll-top`
1. `tip`: 在滚动 `scroll-view` 时会阻止页面回弹，所以在 `scroll-view` 中滚动，是无法触发 `onPullDownRefresh`
1. `tip`: 若要使用下拉刷新，请使用页面的滚动，而不是 `scroll-view` ，这样也能通过点击顶部状态栏回到页面顶部
1. `tip`: scroll-view 自定义下拉刷新节点需要声明为 slot="refresher"，可参考自定义下拉刷新示例
1. `tip`: scroll-view 自定义下拉刷新可以结合 [WXS 事件响应](/miniprogram/dev/framework/view/interactive-animation.md) 开发交互动画

## bind:refresherstatuschange

返回值 `evt.detail = { status, dy }`，其中 `status` 的枚举状态如下

```js
export enum RefreshStatus {
  // 空闲
  Idle,
  // 超过下拉刷新阈值，同 bind:refresherwillRefresh 触发时机
  CanRefresh,
  // 下拉刷新，同 bind:refresherrefresh 触发时机
  Refreshing,
  // 下拉刷新完成，同 bind:refresherrestore 触发时机
  Completed,
  // 下拉刷新失败
  Failed,
  // 超过下拉二级阈值
  CanTwoLevel,
  // 开始打开二级
  TwoLevelOpening,
  // 打开二级
  TwoLeveling,
  // 开始关闭二级
  TwoLevelClosing,
}
```

## 下拉二级

**相关接口**
- 触发下拉刷新 [ScrollViewContext.triggerRefresh](https://developers.weixin.qq.com/miniprogram/dev/api/ui/scroll/ScrollViewContext.triggerRefresh.html)
- 关闭下拉刷新 [ScrollViewContext.closeRefresh](https://developers.weixin.qq.com/miniprogram/dev/api/ui/scroll/ScrollViewContext.closeRefresh.html)
- 触发下拉二级 [ScrollViewContext.triggerTwoLevel](https://developers.weixin.qq.com/miniprogram/dev/api/ui/scroll/ScrollViewContext.triggerTwoLevel.html)
- 关闭下拉二级 [ScrollViewContext.closeTwoLevel](https://developers.weixin.qq.com/miniprogram/dev/api/ui/scroll/ScrollViewContext.closeTwoLevel.html)

下拉二级是下拉刷新的一部份，需同时开启 `refresher-enabled` 和 `refresher-two-level-enabled`。

```html
<scroll-view 
  type="list" 
  scroll-y 
  refresher-enabled="{{true}}" 
  refresher-two-level-enabled="{{true}}"
  refresher-two-level-scroll-enabled="{{true}}"
>
  <view slot="refresher"></view>
</scroll-view>
```

1. 当用户下拉 `scroll-view` 至 `refresher-threshold` 时松手触发下拉刷新
2. 继续下拉至 `refresher-two-level-threshold` 松手触发下拉二级
3. 开启 `refresher-two-level-scroll-enabled` 后，二级页面可以滑动关闭，是否关闭的阈值由 `refresher-two-level-close-threshold` 指定
4. 下拉刷新和下拉二级的展示区域由 `slot=refresher` 定义，开发者可根据 `refresherstatuschange` 判定当前阶段，展示不同内容，例如

```js
buildText(status: RefreshStatus) {
  switch (status) {
    case RefreshStatus.Idle:
      return '下拉刷新'
    case RefreshStatus.CanRefresh:
      return '松手刷新，下拉进入二楼'
    case RefreshStatus.Refreshing:
      return '正在刷新'
    case RefreshStatus.Completed:
      return '刷新成功'
    case RefreshStatus.Failed:
      return '刷新失败'
    case RefreshStatus.CanTwoLevel:
      return '松手进入二楼'
    default:
      return ''
  }
},
```

下拉二级示例代码: [在开发者工具中预览效果](https://developers.weixin.qq.com/s/AI6cwSmP73Jv)

## 嵌套模式

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

```html
<!-- 外层 scroll-view -->
<scroll-view 
  type="nested" 
  scroll-y 
  refresher-enabled="{{true}}"
>
  <view slot="refresher">自定义 refresher</view>
  <nested-scroll-header><view>外层 scroll-vew 的节点 1</view></nested-scroll-header>
  <nested-scroll-header><view>外层 scroll-vew 的节点 2</view></nested-scroll-header>
  <nested-scroll-body>
    <swiper>
      <swiper-item>
        <!-- 里层 scroll-view -->
        <scroll-view type="list" associative-container="nested-scroll-view">
          <view>里层 scroll-vew 的节点 1</view>
          <view>里层 scroll-vew 的节点 2</view>
        </scroll-view>
      </swiper-item>
      <swiper-item></swiper-item>
      <swiper-item></swiper-item>
    </swiper>
  </nested-scroll-body>
</scroll-view>
```

1. 外层 `scroll-view` 的子节点只支持 `nested-scroll-header` 和 `nested-scroll-body` 和自定义 refresher
2. 外层 `scroll-view` 的子节点中只能有一个 `nested-scroll-body`
3. `nested-scroll-header` 和 `nested-scroll-body` 只能有一个子节点
4. `nested-scroll-header` 只能渲染在 `nested-scroll-body` 上面
5. 嵌套滚动策略：当向下滚动时，先滚动外层 `scroll-view` 再滚动里层 `scroll-view`；当向上滚动时，先滚动里层 `scroll-view` 再滚动外层 `scroll-view`

嵌套模式示例代码: [在开发者工具中预览效果](https://developers.weixin.qq.com/s/1IaEOym777Mx)

## 列表构造器

skyline 渲染模式下，如果列表项特别多的场景可以考虑使用列表构造器，可以实现可回收列表，回收的范围取决于 `cache-extent` 配置。默认情况下列表项进入视口时会被创建，而离开视口外则会被回收，即在屏的列表项才会被真正创建出来。

```html
<scroll-view 
  type="custom" 
  scroll-y
>
   <list-builder
    list="{{list}}"
    child-count="{{list.length}}"
    child-height="200"
    bind:itembuild="onItemBuild"
    bind:itemdispose="onItemDispose"
  >
    <view slot:item slot:index style="height: 200px;">
      <view>{{index}}</view>
    </view>
  </list-builder>
</scroll-view>
```

```js
Component({
  data: {
    list: [
      ...
    ]
  },

  methods: {
    onItemBuild(evt) {
      console.log('build', evt.detail.index)
    },

    onItemDispose(evt) {
      console.log('dispose', evt.detail.index)
    },
  },
})
```

1. `scroll-view` 必须设置成 `custom` 模式
2. 列表项默认为定高模式，需要通过 `child-height` 指定，所有列表项必须等高
3. 不定高模式下因为无法知道未创建的列表项高度，会存在滚动条跳动问题
4. 默认情况下不在视口中的列表项不会被创建。在滚动过程中，会根据 `child-count` 判断需不需要创建/回收列表项，如果需要则会进行列表项的创建/回收，同时触发对应事件
5. 目前只支持纵向滚动列表
6. 不支持 `scroll-into-view`

列表构造器示例代码: [在开发者工具中预览效果](https://developers.weixin.qq.com/s/wiAQEwmN7VRz)

## 网格构造器

网格构造器和列表构造器的不定高模式类似，可参考列表构造器的使用方法和注意事项。

```html
<scroll-view 
  type="custom" 
  scroll-y
>
   <grid-builder
    list="{{list}}"
    child-count="{{list.length}}"
    cross-axis-count="4"
		cross-axis-gap="8"
		main-axis-gap="8"
  >
    <view slot:item slot:index style="height: 200px;">
      <view>{{index}}</view>
    </view>
  </grid-builder>
</scroll-view>
```

```js
Component({
  data: {
    list: [
      ...
    ]
  },
})
```

网格构造器示例代码: [在开发者工具中预览效果](https://developers.weixin.qq.com/s/GSAP4wms7LRe)

## 示例代码

自定义下拉刷新示例代码: [在开发者工具中预览效果](https://developers.weixin.qq.com/s/jdabLymn71Mo)

[在开发者工具中预览效果](https://developers.weixin.qq.com/s/QS63PSmM7SJq)
