Skip to content

n-list 列表 ​

组装普通纵向列表:数据行、首尾内容、原生下拉刷新和触底事件。标准行复用 n-cell;网络请求、分页与加载状态由调用方管理,底部提示可直接组合 n-loadmore。

平台兼容性 ​

Web 与微信小程序已完成示例及复制页面运行验证;Android 与 iOS 模拟器字节码目标已编译通过。鸿蒙因本机缺少工具链尚未编译;各 App 设备运行及真机下拉触感尚未验证,不将编译通过视为设备验收通过。

如何调用 ​

html
<n-list title="账号设置" :list="rows" footer="选择项目查看详情" @click="onRowClick" />
ts
import { ref } from "vue";
import { type NListClick } from "@/uni_modules/new-ui/components/n-list/props";
const rows = ref<UTSJSONObject[]>([
	{ id: 1, title: "账号与安全", value: "已保护", arrow: true },
	{ id: 2, title: "暂不可用", disabled: true }
]);
function onRowClick(detail: NListClick): void {
	uni.showToast({ title: `选择第 ${detail.index + 1} 行`, icon: "none" });
}

height 默认 0,内容自然撑高。正数开启内部纵向滚动;virtual 默认开启,此时 itemHeight 为固定行高,组件只挂载可见行和缓冲行。多行文字、图片自然高度或需要保留屏外未提交输入时关闭 virtual。窗口渲染会卸载屏外行,业务编辑状态应绑定数据。

item 插槽接管完整行,仍由组件派发行点击;内部按钮等独立操作使用 click.stop 防止冒泡。Web 标准行支持键盘激活;提供 item 后,行作为列表项容器,插槽内的主操作和独立操作应各用可聚焦按钮承载。默认插槽追加自由内容,不派发数据行 click。数据源不被组件修改。

下面是可独立运行的刷新与分页页面。计时器模拟请求,正式使用时替换为业务接口,并保留并发守卫和过期结果检查。

html
<template>
	<n-page>
		<n-list ref="listRef" :list="rows" :height="300" refresher-enabled @refresherrefresh="onRefresh" @scrolltolower="loadMore">
			<template #bottom><n-loadmore :status="loadStatus" @loadmore="loadMore" /></template>
		</n-list>
	</n-page>
</template>
<script setup lang="uts">
import { ref } from "vue";
import { type NLoadmoreStatus } from "@/uni_modules/new-ui/components/n-loadmore/props";
const listRef = ref<NListComponentPublicInstance | null>(null);
const rows = ref<UTSJSONObject[]>([{ id: 1, title: "第一条记录" }]);
const loadStatus = ref<NLoadmoreStatus>("loadmore");
let timer = -1;
let revision = 0;
let pending = false;
function requestRows(refresh: boolean): void {
	if (pending) return;
	pending = true;
	loadStatus.value = "loading";
	const request = ++revision;
	timer = setTimeout((): void => {
		timer = -1;
		if (request != revision) return;
		const start = refresh ? 0 : rows.value.length;
		const page: UTSJSONObject[] = [];
		for (let i = 0; i < 20; i++) page.push({ id: start + i + 1, title: `列表记录 ${start + i + 1}` });
		rows.value = refresh ? page : rows.value.concat(page);
		pending = false;
		loadStatus.value = "loadmore";
		listRef.value?.stopRefresh();
	}, 600);
}
function loadMore(): void { requestRows(false); }
function onRefresh(): void {
	if (timer != -1) clearTimeout(timer);
	timer = -1;
	revision++;
	pending = false;
	requestRows(true);
}
onUnload((): void => { revision++; if (timer != -1) clearTimeout(timer); });
</script>

接口失败应保留原数据并给出明确反馈,同时释放 pending、恢复 loadStatus,并调用 stopRefresh()。示例的一键复制包含当前数据、配置、插槽、模拟失败及请求清理。

header/footer 位于滚动容器外,替换标题与说明;top/bottom 位于滚动内容内。刷新插槽由原生滚动控件承载,组件不通过手写拖动模拟刷新。自定义刷新节点显式宽高,并放在滚动容器最后一个子元素。

数据标识 ​

nodeKey 默认 id,字符串与数字分别识别;缺少标识时按对象身份保持当前挂载行。重复的显式标识会触发 error 并停止数据行渲染,修正后恢复。需要在不可变数据更新或重新请求后继续复用行时,应提供稳定的唯一标识。

scrollIntoView 可直接填写业务标识,例如 :scroll-into-view="1000" 定位数字 id=1000 的屏外行,无需访问实例内部数据。目标数据稍后到达或顶部插槽高度变化时会重新定位。数字仅匹配数字标识;字符串先匹配组件生成的行 ID,再匹配字符串标识,最后匹配数字标识的文本表示。getScrollTarget() 可将当前生成行 ID 还原为原类型的业务标识,适合复制配置和保存定位状态;没有业务标识的行应先补充稳定 nodeKey,再跨实例保存定位。

定制范围 ​

主题令牌优先;customClass 必须定义于组件自己的样式表。根样式通过 customStyle,内部节点分别通过 titleStyle/titleTextStyle、footerStyle/footerTextStyle、bodyStyle、itemStyle。

窗口模式下 bodyStyle/itemStyle 中影响几何的尺寸、内外边距、边框宽度、定位和 transform 声明被移除,圆角和边框颜色保留;固定高度与占位统一由 itemHeight 管理。文字和复杂行布局由 item 插槽定制。非窗口模式不限制上述样式。整组外边距使用 customStyle,标题背景、留白、颜色和字号使用对应 Style,避免同义属性。

API ​

属性 ​

参数 说明 类型 默认值
list 数据源;标准项读取 title/label/value/arrow/disabled,复杂内容使用 item 插槽 UTSJSONObject[] []
nodeKey 唯一标识字段;字符串与数字区分,缺省使用对象身份,重复标识触发 error 并停止数据项渲染 string id
height 滚动视口高度(px);0 随内容撑高,正数开启内部纵向滚动;外层标题与说明不计入高度 number 0
virtual 限高时仅渲染可见行及缓冲行;行高由 itemHeight 统一管理,复杂不等高内容请关闭 boolean true
itemHeight 窗口渲染的固定行高(px),须为不小于 40 的有限数;非窗口模式不限制行高 number 50
bufferSize 可见区域上下各预渲染的行数,须为非负整数 number 15
scrollTop 目标纵向滚动位置(px),须为有限非负数;不随手动滚动回写 number 0
scrollIntoView 定位到业务 nodeKey 或子节点 ID;数字只匹配数字标识,字符串依次匹配生成行 ID、字符串标识、数字标识的文本表示 string / number
scrollWithAnimation 属性定位和 scrollToTop 是否使用原生滚动动画 boolean false
showScrollbar 显示原生纵向滚动条 boolean false
upperThreshold 距顶部多少 px 触发 scrolltoupper,须为有限非负数 number 50
lowerThreshold 距底部多少 px 触发 scrolltolower,须为有限非负数 number 50
refresherEnabled 限高时开启原生下拉刷新;请求完成后通过实例 stopRefresh() 结束 boolean false
refresherThreshold 下拉刷新触发距离(px),须为有限正数 number 50
refresherBackground 刷新区域背景色;空 = 透明 string
refresherDefaultText 默认下拉文字;空 = 内置语言包 string
refresherPullingText 超过刷新阈值时的文字;空 = 内置语言包 string
refresherRefreshingText 请求中的刷新文字;空 = 内置语言包 string
showBackTop 限高列表滚动超过阈值时显示返回顶部按钮,复用 n-back-top boolean false
title 列表标题;header 插槽提供时替代文字 string
footer 列表末尾说明;footer 插槽提供时替代文字 string
border 数据项之间显示分隔线;最后一项不绘制 boolean true
topBorder 内容区域的顶部边线 boolean true
bottomBorder 内容区域的底部边线 boolean false
borderColor 边线颜色;空 = 主题边框色 string
topLeft 顶部边线左侧内缩(px),须为有限非负数 number 0
topRight 顶部边线右侧内缩(px),须为有限非负数 number 0
bottomLeft 底部边线左侧内缩(px),须为有限非负数 number 0
bottomRight 底部边线右侧内缩(px),须为有限非负数 number 0
titleStyle 标题容器样式,可调整背景和内边距 string
titleTextStyle 标题文字样式,可调整颜色、字号和字重 string
footerStyle 末尾说明容器样式,可调整内边距 string
footerTextStyle 末尾说明文字样式,可调整颜色与字号 string
bodyStyle 内容容器样式;窗口几何由组件管理,不接受 height/min-height/max-height/padding/border 等改变尺寸的声明 string
itemStyle 数据行容器样式;窗口模式不接受改变固定行高的尺寸、内外边距或边框声明 string
customClass 根节点额外类,须在组件自己的样式表中定义 string
customStyle 根节点行内样式;内部滚动视口高度只由 height 管理 string

事件 ​

事件名 说明
click 点击数据行时触发,参数 {item,index};禁用行不触发,插槽内独立操作可用 click.stop
scroll 内部纵向滚动时触发,参数为原生 UniScrollEvent
scrollend 内部滚动结束时触发,参数为原生 UniScrollEvent
scrolltoupper 内部滚动进入顶部阈值时触发,参数为原生 UniScrollToUpperEvent
scrolltolower 内部滚动进入底部阈值时触发,参数为原生 UniScrollToLowerEvent,可衔接加载更多
refresherpulling 下拉时触发,参数为原生 UniRefresherEvent
refresherrefresh 下拉达到阈值并释放时触发;请求完成须调用 stopRefresh,同次刷新不重复触发
refresherrestore 下拉刷新控件复位时触发,参数为原生 UniRefresherEvent
refresherabort 下拉刷新中止时触发,参数为原生 UniRefresherEvent
error 属性或数据标识非法时触发,参数 {prop,message};修正后自动恢复

插槽 ​

插槽名 说明
header 替换 title;位于滚动视口上方,常驻并自然占位
footer 替换 footer 说明;位于滚动视口下方,常驻并自然占位
top 滚动内容前置区;实际高度参与可见窗口计算
item 数据行;参数 item、index(源下标)、last、id(本组件生成的行 ID)
default 在数据行后追加自由内容;自行组装 n-cell 或其他内容,不产生逐行 click
bottom 滚动内容末尾;适合 n-loadmore 等加载提示
empty 数据为空且未提供默认插槽时的内容,默认复用 n-empty
refresher 原生刷新区;参数 status(default/pulling/refreshing)、text

方法 ​

方法名 说明
stopRefresh() 请求结束后调用,停止下拉刷新;不会修改数据源
scrollToTop() 返回内部滚动视口顶部;是否平滑由 scrollWithAnimation 决定
getScrollTarget() 返回当前目标对应的 string/number 业务标识;无业务标识时保留原生节点目标,适合复制配置及保存定位状态

样式令牌 ​

CSS 变量 默认值 作用
--n-list-padding-x 16px 首尾与分隔线的水平内缩
--n-list-font-size 14px 标题、说明与刷新文字字号
--n-list-title-padding-top 16px 标题上留白
--n-list-title-padding-bottom 10px 标题下留白
--n-list-footer-padding-top 10px 末尾说明上留白
--n-list-footer-padding-bottom 0px 末尾说明下留白
--n-list-disabled-opacity 0.5 自定义数据行禁用透明度;标准行使用 n-cell 的令牌
--n-list-pressed-background rgba(0,0,0,0.08) 自定义数据行按压底色

实现说明 ​

能力 常见做法 本组件做法与取舍
标准列表行 容器再实现一套行布局与箭头 复用 n-cell;图片、图标、折叠和侧滑通过 item 组合现有组件
普通容器 标题、末尾说明、上下边线及独立内缩 保留全部布局能力;字号、颜色、背景及留白收敛到已有 Style 定制通道
长列表 固定行高、缓冲窗口与上下占位 复用共享窗口工具,支持关闭窗口以使用自然高度;顶部内容按真实高度测量,不依赖业务填写预留高度
下拉刷新 原生滚动组件手势与业务回调 透传完整刷新事件、阈值和背景,三态文案跟随语言;stopRefresh 显式结束,不加入固定延时或模拟触感
触底加载 列表容器内置请求或独立加载提示 容器仅派发事件;n-loadmore 显示状态,调用方管理网络、并发与重试
返回顶部 在列表内再实现一个浮动按钮 showBackTop 复用 n-back-top,直接调用统一的回顶函数
索引与分组 通用滚动列表同时包含索引、分组与勾选 由 n-index-list 承担完整职责,避免两个组件维护同一组公共 API;普通纵向列表使用本组件,横向浏览使用 n-scroll-list
实例调用 字符串分发或不明确的实例类型 defineExpose 暴露方法,使用编译器生成的明确实例类型直接调用

记录 · 思考 · 创作