免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

uni-app x 复杂列表开发指南:长列表复用、swiper 切换、吸顶与嵌套滚动实战

uni-app x 复杂列表开发指南:长列表复用、swiper 切换、吸顶与嵌套滚动实战 uni-app x 复杂列表开发指南长列表复用、swiper 切换、吸顶与嵌套滚动实战【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app复杂列表是移动端 App 最典型的交互形态顶部 Tab 左右滑动切换多组列表、表头吸顶、子列表与父容器协同滚动。本篇以 uni-app x 的滚动视图体系scroll-view、list-view、waterflow为核心由浅入深讲解长列表的 recycle 复用机制、三种吸顶实现方案监听滚动 transform、sticky-header/sticky-section 组件、嵌套滚动模拟、以及 scroll-view 的嵌套滚动协商能力并给出可直接落地运行的配置与源码示例。为什么复杂列表要关注滚动视图的选择在 App 开发中复杂列表通常意味着三件事列表足够长数千条 item、列表可以横向切换swiper-list、列表带有吸顶/嵌套滚动表头固定、子容器协同滚动。uni-app x 提供两个滚动视图组件scroll-view 与 list-view它们的能力边界不同scroll-view灵活、通用支持横向/竖向/双向滚动可作为任何内容的可滚动容器但没有自带 recycle复用机制所有子节点都会真实创建。list-view专为长列表设计底层复用原生 view无论列表多长系统都会自动回收和复用渲染资源体验与原生应用一致但结构上有特殊限制例如吸顶必须使用专用组件。选择原则很直接列表 item 很多用 list-viewitem 少、需要灵活嵌套与协商滚动用 scroll-view。二者在长列表场景下的性能差异详见 长列表性能。长列表必须使用 recycle 机制原生开发一般使用 recycle-view 做复用只保留有限的原生 view数屏之外的 view 被回收并根据在屏状态为 view 装载不同数据。uni-app x 中 list-view 组件 与 waterflow 组件内部就是复用原生 view 的实现分别对应普通长列表与瀑布流长列表。使用这两个组件无论列表多长系统都会自动回收和复用渲染资源。需要注意list-view / waterflow 只负责渲染层的资源复用不处理 Vue 的 VNode 与 Element 复用。如果一次性加载数千条本地记录VNode 和 UniElement 数量过多创建过程本身就会很慢。此时还有两种补充手段详见 长列表性能uni-recycle-view 组件内部计算决定哪些数据需要展示只创建有限的 VNode从整体上控制 DOM 与原生 view 数量但滚动流畅度低于 list-view且 2.0 起要求所有 item 高度一致、不支持瀑布流。分批加载针对初始大批量数据延迟分批渲染并在用户滚动、下拉刷新期间暂停加载闲时加载避免阻塞 UI。无论采用哪种方案务必控制每个 list-item 内的组件数量——它是 DOM 元素的放大器。例如评星组件若用 5 个 view 实现每个 item 就多出 5 个 view列表一长 DOM 数量会惊人推荐像 hello uni-app x 复杂列表示例那样用一个 text 组件内的字体图标字符代替。本仓库 src/pages/template 下提供了完整的长列表实战样例包括long-list、long-list2、long-list-batch分批加载、long-list-deleteable、long-list-nested嵌套滚动长列表、long-list-perf性能对照、custom-long-list等目录可直接对照阅读。列表的左右滑动swiper-listAndroid/iOS App 常见的列表形态是顶部一个 Tab下方列表可左右滑动切换即swiper-list。此时页面结构为顶部一个 tab 组件 一个 swiper 组件每个 swiper-item 中放入一个 list-view。swiper :currentdata.current changeonSwiperChange swiper-item v-for(tab, index) in data.tabs :keyindex list-view !-- 每个 tab 对应的长列表 -- /list-view /swiper-item /swiper基础版样例仅 Tab 切换、未放入真实列表数据Tab 为下划线方式本仓库 src/pages/template/swiper-list及 swiper-list2即对应 hello uni-app x 中 swipe-tabs-underline / swipe-tabs-scale-highlight 的思路——前者下划线跟随滑动后者当前项字体放大高亮。放入真实数据的完整版表头吸顶 左右滑动 嵌套滚动的综合样例对应本仓库 src/pages/template/swiper-list 与long-list-nested目录后者在下文嵌套滚动章节会详细拆解。需要特别指出list-view 一旦嵌入 swiper-item就进入了横向父容器 竖向子容器的组合场景若还想在父容器实现吸顶、表头固定等复杂效果基本都要依赖嵌套滚动见下文。吸顶sticky的三种实现方式吸顶在 Web 里是一个 CSS 属性但相比原生能力不够灵活。在 uni-app x 中实现吸顶有三种做法适用于不同场景。方式一监听滚动事件 transform 固定位置监听滚动事件调用元素的transform属性把某个 view 的 top 始终固定在一个位置、不跟随滚动从而实现吸顶。得益于 uni-app x 无通信性能问题逻辑层与渲染层不存在频繁 IPC 的性能损耗上述做法也能流畅实现。对应示例见本仓库 src/pages/template/scroll-sticky即 hello uni-app x 中 scroll-view-sticky-section 的实现核心思路是在 scroll-view 的scroll回调里根据event.detail.scrollTop计算偏移量并设置目标元素的 transform。适用场景scroll-view 作为滚动容器。这种方式实现直观、无组件依赖但不适合 list-view——因为 list-view 底层有 view 复用机制脱离滚动流的元素会被回收存在特殊限制。方式二sticky-header / sticky-section 组件list-view 中实现吸顶需要使用官方吸顶组件。二者分工如下sticky-header组件类型UniStickyHeaderElement文档见 sticky-header作为 list-view 的一级子组件把需要吸顶的内容放入其中后该组件滚动到列表顶部时不再继续向上滚动、固定在列表顶端向下滚动时可以自由滚动甚至滚出屏幕。sticky-section组件类型UniStickySectionElement文档见 sticky-section作为 sticky-header 的父容器负责控制子元素的滚动吸顶业务。多个 sticky-section 组合可实现分段吸顶例如通讯录的字母分段吸顶、多店铺购物车的店铺分段吸顶。一个典型场景是列表到详情页面整个页面就是一个 list-view包括顶部的 banner、中间的表头和下面的 list-item中间的表头放入 sticky-header 组件中实现吸顶对应 hello uni-app x 的 news-feed-list 样例本仓库 src/pages/template/list-news 即新闻列表类实现。sticky-header 基础用法list-view idlist-view styleflex: 1; background-color: #f5f5f5; sticky-header !-- 固定到父元素顶部的元素 -- text stylepadding: 20px; background-color: #f5f5f5;向上滑动页面体验sticky-header吸顶效果。/text /sticky-header list-item v-forindex in 20 :keyindex stylepadding: 15px; margin: 5px 0;background-color: #fff;border-radius: 5px; text classtextitme-content-{{index}}/text /list-item /list-viewsticky-section 分段吸顶用法list-view idlist-view styleflex: 1; background-color: #f5f5f5; sticky-section v-forsectionId in 3 :idsectionId push-pinned-headerfalse :preloadtrue sticky-header text stylepadding: 20px; background-color: #f5f5f5;sticky-header吸顶--{{sectionId}}/text /sticky-header list-item v-forindex in 20 :keyindex stylepadding: 15px; margin: 5px 0;background-color: #fff;border-radius: 5px; text classtextitme-content-{{index}}/text /list-item /sticky-section /list-view关键属性一览| 组件 | 属性 | 类型 | 默认值 | 说明 | | :- | :- | :- | :- | :- | | sticky-header | padding | Arraynumber | [0,0,0,0] | 长度为 4 的数组按 top、right、bottom、left 顺序指定内边距 | | sticky-section | push-pinned-header | boolean | true | 多个 sticky-section 吸顶重叠时是否继续上推 | | sticky-section | preload | boolean | false | 仅在 App 平台蒸汽Vapor模式支持设为 true 时 section 在滚动到之前就渲染避免 index-bar 等直接跳转场景出现空白/闪烁 | | sticky-section | padding | Arraynumber | [0,0,0,0] | 同 sticky-header |使用注意事项同时适用于两个组件sticky-header 仅支持作为 list-view、sticky-section 的子节点sticky-section 仅支持作为 list-view 的子节点。同一父元素下不能存在多个 sticky-header多个吸顶需分别放入 sticky-section 中。两个组件都不支持设置 CSS 样式不要通过 class 和 style 设置样式鸿蒙平台暂不支持 padding 属性可通过设置子元素样式实现类似效果。Android/iOS 平台同一个 sticky-section 可存放多个 sticky-header多个吸顶滚动时后一个会停靠在前一个的末尾处多个 sticky-section 之间的吸顶停靠由 push-pinned-header 控制。鸿蒙平台 sticky-header 只能作为 sticky-section 的子元素使用API 版本低于 17 的设备不支持 sticky-header可自行监听滚动、设置某区域 top 为固定值即方式一。蒸汽模式Vapor下sticky-header 必须是 sticky-section 内首个元素且每个 sticky-section 下仅支持一个 sticky-headersticky-section 内的 list-item 必须使用 v-for 且必须有 key不能使用 v-if。Android 平台 sticky-section 作为 list-view 子元素时其子元素仅支持 sticky-header、list-item其他元素无法正常显示。方式三用嵌套滚动模拟吸顶scroll-view 作为父容器时可以和子滚动容器子 scroll-view 或子 list-view嵌套并协商嵌套滚动的逻辑。子容器滚动时可以通知父容器现在要滚动了你打算怎么处理——是跟着一起滚、滚动一点、还是不动。如果父容器的逻辑是滚动到一定条件后就不再滚动那么在视觉上就达到了吸顶的效果——但代码逻辑并不是吸顶而是滚动协商的结果。这种方式的实际价值在于它不止能模拟吸顶还能实现更复杂的父-子滚动编排如表头先滚出、内容区再滚出或反之。具体协商机制见下一章节。嵌套滚动nested父子滚动容器的协商嵌套滚动是手机 OS 原生提供的一种强大能力在较小的屏幕空间里通过编程充分控制某些内容的显示与滚出屏幕外。scroll-view 作为父容器时可以与子滚动容器子 scroll-view 或子 list-view嵌套并协商滚动逻辑。完整的组件说明见 scroll-view 文档。模式一nested 嵌套模式nested-scroll-header / nested-scroll-body适用于两个 scroll-view 相互嵌套、滚动衔接不顺滑的场景。开启方式VDOM 模式蒸汽模式已废弃外层 scroll-view 设置typenested切换为嵌套模式内层 scroll-view 设置associative-containernested-scroll-view开启与外层 scroll-view 的嵌套滚动。scroll-view styleflex:1 typenested nested-scroll-header !-- 固定在嵌套区域顶部的部分 -- /nested-scroll-header nested-scroll-body scroll-view styleflex:1 associative-containernested-scroll-view !-- 内层可滚动内容 -- /scroll-view /nested-scroll-body /scroll-view注意事项外层 scroll-view 的子节点只支持 nested-scroll-header、nested-scroll-body 和自定义 refresher其中只能有一个 nested-scroll-bodynested-scroll-header 只能渲染在 nested-scroll-body 上方二者各只能有一个子节点。蒸汽模式已简化废弃 type 属性内层 scroll-view 只需设置associative-containernested-scroll-view即可开启嵌套模式外层也可不强制使用 header/body 组件。完整示例见本仓库 src/pages/template/long-list-nested。模式二nested-scroll 嵌套滚动协商custom-nested-scroll这是另一种更细粒度的协商机制仅 Android VDOM 模式支持蒸汽模式无效且仅支持竖向滚动。参与方为父 scroll-view协商的裁判与子滚动容器list-view、waterflow、scroll-view 均支持作为子方。协商流程子滚动容器设置custom-nested-scrolltrue开启与父组件的嵌套滚动协商。子组件准备滚动时父组件触发startnestedscroll事件父组件响应事件并return true表示与子组件建立嵌套滚动协商默认 return false。协商建立后子组件滚动时父组件持续收到nestedprescroll事件事件携带{deltaX, deltaY}含义是嵌套滚动即将发生。父组件在回调中执行event.consumed(x, y)告知子组件本次 deltaX、deltaY 各消耗多少即父容器消费掉多少滚动距离子组件滚动剩余的差值。父组件配置nested-scroll-child子元素id后父组件惯性滚动时会让该子元素进行滚动从而触发 nestedprescroll 协商该子元素必须同时设置custom-nested-scrolltrue否则配置无效。滚动停止或意外终止后触发stopnestedscroll事件。scroll-view styleheight: 100%; scroll-ytrue bouncesfalse nested-scroll-childlistview startnestedscrollonStartNestedScroll nestedprescrollonNestedPreScroll stopnestedscrollonStopNestedScroll !-- 父容器其余内容 -- list-view idlistview classchild-scroll scroll-ytrue custom-nested-scrolltrue !-- 子列表内容 -- /list-view /scroll-view// 建立嵌套滚动协商 const onStartNestedScroll (event : UniStartNestedScrollEvent) : boolean { return true } // 消耗子组件的部分滚动距离 const onNestedPreScroll (event : UniNestedPreScrollEvent) { // 例如父容器先消费 100px 的竖向滚动其余交给子列表 event.consumed(0, 100) }限制清单嵌套滚动协商仅在 Android VDOM 模式支持蒸汽模式下无效仅支持竖向滚动横向滚动不支持nested-scroll-child 指向的元素必须设置custom-nested-scrolltrue与 nested 嵌套模式不兼容scroll-view 设置嵌套模式后嵌套滚动手势协商相关事件不会触发nested-scroll-child属性只接受 id不支持 ref。相关事件与属性在 scroll-view 组件文档 中有完整定义custom-nested-scroll、nested-scroll-child、startnestedscroll、nestedprescroll、stopnestedscroll。综合实战表头吸顶的可左右滑动长列表把上述能力组合起来就是常见电商/资讯 App 的首页-频道结构顶部 Tab 可左右滑动切换列表 表头吸顶 每个频道内部是长列表。由于 list-view 被嵌入 swiper想在父容器实现复杂效果时大多要使用嵌套滚动。该综合样例对应 hello uni-app x 的 banner-tabs-long-list-nested-scroll本仓库 src/pages/template/swiper-list 与long-list-nested、long-list-perf目录提供了可运行的参考实现结构为页面 ├── tab 组件左右滑动切换 └── swiper └── swiper-item每个频道 ├── 表头吸顶部分 └── list-view / scroll-view长列表嵌套滚动协商结语复杂列表方案的选型速查| 需求 | 推荐方案 | 关键约束 | | :- | :- | :- | | 超长列表数千条 | list-view / waterflow自动 recycle | 控制 item 内组件数量list-view 内吸顶须用专用组件 | | 一次性加载大量本地数据 | uni-recycle-view 或分批加载 | recycle-view 要求 item 等高分批加载注意闲时加载 | | 顶部 Tab 左右切换列表 | swiper 每个 item 内 list-view | 父容器复杂效果需嵌套滚动配合 | | scroll-view 内吸顶 | 监听滚动 transform 固定 | 实现简单但 list-view 不适用 | | list-view 内吸顶 | sticky-header / sticky-section | 不支持 CSS 样式分段吸顶用 sticky-section | | 父子滚动容器协同编排 | typenested 嵌套模式VDOM/ associative-containerVapor | nested-scroll-header/body 结构约束 | | 细粒度滚动协商吸顶模拟等 | custom-nested-scroll startnestedscroll/nestedprescroll | 仅 Android VDOM仅竖向 |以列表的实际数据规模、容器嵌套层级和目标平台VDOM 还是蒸汽模式为起点先在 scroll-view 与 performance.md 长列表章节 确认能力边界再对照 src/pages/template 下的 swiper-list、long-list-nested、long-list-perf、scroll-sticky、long-list-batch 等参考实现动手改造即可把上述三种吸顶方案与两种嵌套滚动模式灵活组合进自己的页面。【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表