Skip to content

n-picker-view 滚轮选择视图 ​

说明 ​

数据驱动的多列滚轮选择视图(纯视图):columns 传入列数据、v-model 绑逐列选中下标,滚动停止后回发选中结果。没有弹层壳、触发器与确认按钮——嵌入任意容器或自组弹层时用它;完整选择器交互(触发器 + 底部弹层 + 工具栏)用 n-picker,弹层壳用 n-popup。

级联(省市区、分类树等)由使用方编排:在 change 回调里按新游标重建 columns 传入即可,组件自动把越界游标钳回有效范围。注意级联场景的载荷语义:indexes 是换列的依据;values / labels 反映的是滚动发生时传入的旧列数据(新列尚未重建)——最终值请在换列后沿新列自行对齐(与参考实现语义一致)。

平台兼容性 ​

能力 Web 微信小程序 Android iOS 鸿蒙
基础滚轮(滚动 / 受控 / change) ✓ ✓ ✓ ✓ ✓
蒙层(主题渐变) ✓(整体) ✓(整体) ✓(上下两半) ✓(上下两半) 不绘制
表头 / 加载态 / 空态 ✓ ✓ ✓ ✓ ✓

基础用法 ​

vue
<template>
	<n-picker-view
		v-model="indexes"
		:columns="cols"
		:headers="['年', '月']"
		@change="onChange"
	/>
</template>

<script setup lang="uts">
	import { ref } from "vue";
	import { type NPickerViewColumns, type NPickerViewResult } from "@/uni_modules/new-ui/components/n-picker-view/props";

	const cols: NPickerViewColumns = [
		[{ label: "2024", value: "2024" }, { label: "2025", value: "2025" }],
		[{ label: "1 月", value: "1" }, { label: "2 月", value: "2" }]
	];
	const indexes = ref<number[]>([0, 1]);

	function onChange(r: NPickerViewResult) {
		// r.indexes 逐列下标 / r.values 逐列值 / r.labels 逐列文本
	}
</script>

列数据项复用 n-picker 的选项类型(label 展示、value 提交)。异步列数据就绪前可置 loading 显示加载态;columns 为空显示空态占位。

API ​

属性 ​

属性 类型 默认值 说明
modelValue number[] [] 逐列选中下标(v-model);外部赋值滚轮跟随定位,合法值对齐不回发事件;越界值钳制到末项 / 首项、长度不符补 0 截断,修正值回写 v-model
columns NPickerOption[][] [] 列数据:外层为列、内层为该列候选(label 展示、value 提交);空数组显示空态占位
itemHeight number 40 滚轮行高(px)
visibleItemCount number 5 可见行数;滚轮总高 = itemHeight × visibleItemCount,奇数使选中项居中
headers string[] [] 表头文字(逐列,与列对齐等分展示);超出列数的部分截去;加载中与空态不显示
loading boolean false 加载中:滚轮区替换为居中加载指示与文案,适合列数据异步就绪的场景
customClass string "" 挂到根节点的额外 class(类须定义在组件样式表内)
customStyle string "" 根节点行内样式,如 "margin:16px 0"

事件 ​

事件 参数 说明
update:modelValue indexes: number[] 滚动停止后触发,参数为逐列选中下标;配合 v-model 或 :model-value 手动双向绑定
change NPickerViewResult 与 update:modelValue 同时发出,参数为 { indexes, values, labels };级联换列在此回调里进行(values / labels 为滚动时的旧列取值,换列以 indexes 为准)

插槽 ​

无。表头走 headers 属性,加载 / 空态为内置提示。

实例方法 ​

无。程序化定位直接改 modelValue(受控对齐)。

实现说明(参考做法 vs 本库做法) ​

滚轮本体是各端原生 picker-view(Web 4.0 / 微信 4.41 / Android 3.9 / iOS 4.11 / 鸿蒙 4.61),外观装配逐机制对照:

机制 参考做法 本库做法 理由
值与事件 参考一:value 下标 + change-value / change-index 双事件;参考二:value + update:modelValue + change modelValue(v-model 下标)+ change 单载荷三件套(indexes / values / labels)同参同发 库规范 v-model 统一 + 受控双事件通道;单载荷统一双事件语义,与 n-picker 的结果结构同构
列数据类型 参考一:{label, value} 二维;参考二:any 复用 n-picker 的选项类型(NPickerOption[][]) 同族选择器的列项形状一致,跨组件类型复用
高度 参考一:height 属性(默认 300);参考二:visibleItemCount visibleItemCount × itemHeight 推导 同义功能取行业通用的可见行数,行高与指示条高天然一致
行高 参考一:42(iOS 50) 统一 40(与 n-picker 同值) 平台分叉不进库,滚轮族视觉统一
loading 参考二有 loading 属性,源码不可读、无演示页可核实行为 滚轮区替换为居中加载指示(内置 loading 组件)+ 多语言文案 行为无法核实处如实说明;本库实现为提示态覆盖,语义直白
immediateChange 参考二有此属性 不收录 目标端原生 picker-view 无此属性(官方属性表核对),收录即产生编译告警
defaultIndex 参考二有此属性 不收录 受控 modelValue 即定位,双源冗余
confirm / close / cancel 参考二事件表含此三者 不收录 弹层选择器交互事件;纯视图无壳无触发点——弹层与确认交互由 n-picker / n-popup 承担
pickstart / pickend 原生仅微信端支持,两参考组件均未收录 不收录 平台专属且参考未收录,不自行创造 API
Android 文字自绘 参考一在 Android 端用画布接口自绘项文字(大列表性能补偿) 不采纳,四端统一 view + text 渲染 原生 picker-view 已管理滚动区渲染;自绘引入平台画布 API 依赖与文字度量复杂度,收益场景(超长列表)非本组件默认形态
选中项视觉 参考一:深色主题下选中项白字层次 选中项主墨色(text-1)、非选中项次要色(text-2),主题令牌动态类 同功能令牌化融合,浅深主题通用成体系
蒙层 原生蒙层深浅跟随宿主系统,不随组件主题 压平原生蒙层 + 主题背景色自绘渐变(与 n-picker 同款四端变体装配) 组件主题与宿主系统深浅不一致时原生蒙层会压脏界面,实测结论复用
表头 参考一:headers 按列数截取、等分展示 同款 —
结构位翻转 — 加载 / 空态 / 滚轮三态互斥装配收进单一 key 位,键一翻整根重建,重建后按受控值重新定位 动态插拔不即时重绘的平台已知问题,结构位收拢是库级统一解法
越界防护 参考一:change 回调里越界钳制 + 相同值不触发 同款(watch 换列同样钳制) 快速滑动与级联换列的索引越界防护
定位吸收期 —(两参考实现均无此机制) 外部赋值(含越界钳制修正回写)驱动原生滚轮动画期间,中间态 change 只认与目标全等的落位回执;吸收期内用户再滚某列时其回执永不等于目标,超时以最后一次回执对账收敛(不吞用户滚动),与 n-picker 同族同构 程序化定位动画与用户手势并发时,物理落位与逻辑值脱钩是受控滚动组件的通病;吸收 + 对账保证两侧终态一致

注意事项 ​

  • 根节点默认带主题表面底色(浅色 #ffffff / 深色 #171717,蒙层渐变与底色一体);置于异色容器时经 custom-style 覆盖底色。
  • itemHeight 与 visibleItemCount 运行时可变,滚轮总高即时联动。
  • 滚轮滚动交互由各端原生组件承载,本组件不模拟惯性;滚动停止才回发(拖动中间态无事件)。

记录 · 思考 · 创作