n-action-sheet 动作面板
底部弹出的操作菜单:普通操作列表(纵向)与分享面板(layout="share",每行横向、可滚动)共用同一套数据解析、选择守卫与事件出口。弹层骨架(遮罩 / 滑入滑出 / 把手拖拽 / 底部安全区)内嵌 n-popup 承担,本组件只给动作内容:标题与说明、逐项文字 / 说明 / 颜色 / 禁用 / 加载、取消与关闭入口、字符串与对象混合数据、微信开放能力按项承接。
- 受控显隐:
visible置 true 弹出;取消 / 关闭 / 选中自动收起 / 遮罩 / 拖拽 / Web Escape 只派发语义事件并同帧回传update:visible(false)——组件不自行收起,在回调里把visible改回 false 即完成闭环;父组件不回写时面板保持打开并恢复可操作(不产生隐式内部收起)- 数据三种结构(一次输入必须为一种):字符串一维(快捷写法)、对象一维、对象二维(share 布局按行横向排列)。结构混装、缺文字、字段类型错误、重复 id 走
dataError错误态:动作区显示占位说明、保留取消 / 关闭,不再渲染旧数据close事件的含义是「请求收起」,参数区分来源(select / cancel / close / mask / drag / escape)——它不是退场动画完成事件;取消路径另有cancel(来源)与之同帧同发- 禁用 / 加载项做真实拦截:保色相降透明,点击与原生能力均不可用;不绑定原生 disabled
- 微信开放能力按项配置(对象项
openType及配套参数):能力项选中只派发select,原生回调按原生名事件转发,是否收起由业务在回调里决定——auto-close对能力项不生效,避免抢先销毁授权按钮- 高度自适应:短内容自然高度;超出 min(期望高度, 窗口 80%) 时实测三段高度,头部文本与内容区分别压进滚动视口,取消 / 关闭始终可达
平台兼容性
| App | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ小程序 |
|---|---|---|---|---|---|---|
| √ | √ | √ | × | × | × | × |
微信开放能力(open-type 及其参数、回调事件)仅微信小程序端生效;其它端 openType 只是普通数据,选项按普通业务项处理。
API
属性
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|---|---|---|---|---|
| visible | 显隐开关(受控模式:取消/关闭/选中自动收起/遮罩/拖拽只派发语义事件并回传 update:visible(false),收起由使用者改回 false) | Boolean | false | - |
| items | 动作数据:字符串一维 / 对象一维 / 对象二维;一次输入必须为一种结构,混合形状走 dataError 错误态 | Array | [] | - |
| text-key | 对象项主文字字段名(空串按 "text");只映射主文字,其余字段名固定 | String | "text" | - |
| title | 面板标题(空串不占标题空间;替代文本区用 #header 插槽) | String | "" | - |
| description | 面板整体说明(标题下方的次要文字,空串不占位) | String | "" | - |
| layout | 布局:list = 纵向动作列表;share = 分享面板(每行横向、可滚动) | String | "list" | list / share |
| columns | share 每行可视列数;正整数按实际行宽等分,超出横向滚动;0 沿用主题项宽。正值时忽略 align,不足一行从首列对齐 | Number | 0 | ≥0 的整数 |
| variant | 外观:card 独立圆角卡片;line 连续表面,列表内部细分割线,取消区用背景留白分组;不改变交互 | String | "card" | card / line |
| align | share 行内排列:between 在整行放得下时分散到两端(单项居中),放不下回到 start 可滚动 | String | "start" | start / between |
| show-cancel | 显示底部取消入口 | Boolean | true | - |
| cancel-text | 取消按钮文案(空串取内置多语言文案;隐藏取消入口用 show-cancel) | String | "" | - |
| show-close | 标题区右侧关闭按钮(点击等同取消:cancel("close") + 建议收起) | Boolean | false | - |
| auto-close | 可用普通项选中后自动请求收起;异步业务推荐 false。微信能力项不受本项影响 | Boolean | true | - |
| mask-closable | 点击面板外遮罩请求取消并收起;置 false 时遮罩与 Web Escape 不再触发关闭,取消/关闭按钮仍可用 | Boolean | true | - |
| show-handle | 底部把手小条(透传 n-popup) | Boolean | false | - |
| drag-close | 允许头部下拉关闭;复用已有把手与标题区,无头部内容时保留 20px 拖拽区,列表/分享区不参与拖拽 | Boolean | false | - |
| safe-area-inset-bottom | 底部安全区垫层(由 n-popup 自动读取) | Boolean | true | - |
| duration | 出入场过渡时长(毫秒):0 = 即显模式 | Number | 300 | - |
| z-index | 弹层层级:0 = 跟随内置默认(1000);大于 0 写入根节点行内 z-index | Number | 0 | - |
| height | 整个面板的期望高度(px,含标题/列表/取消/安全区):0 = 随内容自适应;超过窗口 80% 按 80% 封顶 | Number | 0 | - |
| max-width | 面板最大宽度(px):实际宽度 = min(窗口宽, max-width),宽屏底部水平居中 | Number | 560 | - |
| radius | 顶部圆角(px):-1 取主题令牌,0 直角 | Number | -1 | - |
| mask-color | 遮罩颜色(非空仅覆盖本实例) | String | "" | 与 css 相同 |
| panel-style | n-popup 面板行内样式(如表面色);不得覆盖其 transform/transition | String | "" | 与 css 相同 |
| title-style | 默认标题文字的行内样式 | String | "" | 与 css 相同 |
| description-style | 默认整体说明文字的行内样式 | String | "" | 与 css 相同 |
| item-style | 每个动作项内容容器的行内样式(不能绕过禁用/加载守卫) | String | "" | 与 css 相同 |
| text-style | 默认项主文字的行内样式 | String | "" | 与 css 相同 |
| item-description-style | 默认逐项说明文字的行内样式 | String | "" | 与 css 相同 |
| icon-style | 图标插槽宿主盒的行内样式(底色、圆角等) | String | "" | 与 css 相同 |
| cancel-style | 取消按钮容器的行内样式 | String | "" | 与 css 相同 |
| custom-class | 挂到弹层根节点的额外 class(类须在组件样式表内定义) | String | "" | - |
| custom-style | 弹层根节点行内样式(z-index 正值优先用 z-index prop) | String | "" | 与 css 相同 |
事件
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| select | 可用项激活时触发一次(含微信能力项);不表示异步业务成功或授权成功 | { row, index, item }:原始位置 + 原始业务对象 |
| cancel | 取消按钮 / 关闭按钮 / 可关闭遮罩 / 头部拖拽 / Web Escape 请求放弃时触发 | String(来源:cancel/close/mask/drag/escape) |
| close | 组件请求收起的来源信号,与 cancel 同帧同发;注意这是「请求收起」,不是退场动画完成事件 | String(来源:select/cancel/close/mask/drag/escape) |
| update:visible | 关闭建议(false):配合 :visible 手动双向控制显隐 | Boolean |
| dataError | 数据 / 配置校验错误;按错误签名变化派发一次 | |
| getuserinfo | open-type=getUserInfo 回调(微信小程序) | { row, index, item, event }:点击时上下文 + 原生事件 |
| contact | open-type=contact 客服会话回调(微信小程序) | |
| getphonenumber | open-type=getPhoneNumber 回调(微信小程序) | |
| getrealtimephonenumber | open-type=getRealtimePhoneNumber 回调(微信小程序) | |
| error | 微信开放能力错误原样透传(与 dataError 数据校验错误无关) | |
| opensetting | open-type=openSetting 授权页关闭后回调(微信小程序) | |
| launchapp | open-type=launchApp 唤起 APP 回调(微信小程序) | |
| chooseavatar | open-type=chooseAvatar 回调(微信小程序) | |
| agreeprivacyauthorization | 用户同意隐私协议回调(微信小程序) | |
| createliveactivity | open-type=liveActivity 订阅回调(微信小程序) |
插槽
| 插槽名 | 说明 |
|---|---|
| header | 替代标题 + 说明文本区(把手与关闭按钮仍由组件管理) |
| prepend | 头部之后、动作数据区之前的补充内容(随内容区滚动) |
| icon | 默认项中的图标内容(只替换图标盒,不拥有点击守卫);参数 { item, row, index };list 图标在文字左、share 在文字上;未提供不留空位 |
| item | 替代单项内容(交互宿主、原生能力、禁用与加载守卫保留);参数 { item, row, index, disabled, loading };不要放入需要独立点击的控件 |
| append | 动作区之后、取消区之前的补充内容(随内容区滚动) |
| footer | 替代默认取消区(组件不解析插槽内部按钮,调用方自行设置 visible=false) |
主题与样式隔离
页面 class 打不进组件内部。定制通道按优先级:
- 主题令牌:
--n-action-sheet-*运行时变量或 uni.scss 覆盖同名$n-action-sheet-* - 根节点
custom-class/custom-style;面板本体走panel-style - 内部节点行内样式 prop(title-style / text-style / icon-style 等)
| 令牌 | 默认值 | 含义 |
|---|---|---|
| --n-action-sheet-radius | 16px | 顶部圆角 |
| --n-action-sheet-padding-x | 10px | 默认内容左右内距 |
| --n-action-sheet-title-size | 16px | 标题字号 |
| --n-action-sheet-description-size | 14px | 整体说明字号 |
| --n-action-sheet-text-size | 14px | 列表主文字字号 |
| --n-action-sheet-item-description-size | 13px | 逐项说明字号 |
| --n-action-sheet-share-text-size | 13px | 分享标签字号 |
| --n-action-sheet-item-min-height | 44px | card 列表项最小高度 |
| --n-action-sheet-cancel-min-height | 44px | card 取消按钮最小高度 |
| --n-action-sheet-cancel-size | 14px | 取消文字字号 |
| --n-action-sheet-cancel-gap | 10px | card 外观取消区与菜单的背景间隔 |
| --n-action-sheet-line-cancel-gap | 8px | line 外观取消区与菜单的背景间隔 |
| --n-action-sheet-line-min-height | 48px | line 列表项与取消按钮最小高度 |
| --n-action-sheet-line-padding-x | 0px | line 列表内容左右内距与分割线两端留白 |
| --n-action-sheet-drag-area-height | 20px | drag-close 开启且没有把手、标题、说明、header 插槽与关闭按钮时的顶部拖拽区高度 |
| --n-action-sheet-divider-width | 0.5px | line 列表内部细分割线高度 |
| --n-action-sheet-divider-color | var(--n-border, #e5e6eb) | line 列表内部细分割线颜色 |
| --n-action-sheet-share-icon-size | 40px | 分享图标盒尺寸 |
| --n-action-sheet-share-item-width | 76px | 分享项定宽 |
| --n-action-sheet-share-row-gap | 4px | 分享行距 |
| --n-action-sheet-icon-text-gap | 4px | 图标与文字间距 |
| --n-action-sheet-disabled-opacity | 0.4 | 禁用透明度 |
| --n-action-sheet-active-opacity | 0.7 | 按压透明度 |
| --n-action-sheet-icon-background | transparent | 图标盒底色 |
文字、表面、分隔线等中性色直接引用全局令牌(--n-text-1 / --n-text-2 / --n-bg-1 / --n-bg-2 / --n-border),随深浅主题自动切换;遮罩复用 --n-popup-mask-color(mask-color prop 覆盖本实例)。
长内容与布局限制
- 面板高度上限为窗口高度的 80%(
heightprop 期望值与之取小);超限后内容区为滚动视口,头部文本超长时同样压进头部滚动区,取消 / 关闭始终可达 - header / footer 插槽自定义内容须自行控制高度:固定区过高会压缩内容区(内容区最低保 120px,实在放不下时以可操作最小高度为准)
- share 行内
align="between"需实测行内容宽度:放得下分散到两端(单项居中),放不下自动回到 start 可滚动,不做假列数切换 - 面板宽度
min(窗口宽, max-width),宽屏底部水平居中;小屏满宽
实现说明
-
分享布局保留主题项宽与横向滚动;columns 为正整数时按实测动作区宽度与主题留白等分可视列,替代调用者计算窗口宽度和硬编码边距。末行从首列起对齐,窗口与面板宽度变化自动重算。
-
外观与布局分离:
variant="card"保留独立圆角和项间距;variant="line"列表与分割线左右铺满、仅非末项显示细线,列表项与取消按钮最小高度均为 48px,取消区前保留 8px 背景间隔。两种外观共享数据、禁用、加载和事件逻辑,share始终保留横向图标布局。运行中切换外观只更新样式与分割线显隐,保留插槽和能力承接节点;默认 card 保持现有用法。 -
弹层骨架零重复:n-popup 是唯一弹层宿主(direction="bottom"、空档位),本组件不复刻遮罩、过渡、拖拽与安全区;n-popup 的 close(reason) 是唯一关闭来源通道,组件统一转换为 cancel + close + update:visible 出口
-
数据边界:输入经显式类型校验后归一为强类型渲染模型;不修改业务数组与对象,不注入内部字段;字符串项的事件 item 是
{ [textKey]: 原字符串 }归一对象,对象项回传原引用 -
能力回调归因:点击时对 item / row / index 与会话标识做快照,原生回调按快照归因并即取即删——列表重排、项删除、面板关闭重开后到达的迟到回调一律作废,不会归到新项或新会话
-
能力承接层:透明空 button 覆盖整项(button 是叶子节点不可嵌内容),禁用 / 加载时只清空 open-type、不销毁节点——已启动回调的接收节点稳定,等待期间不重复启动能力
-
高度策略:打开时以 selectorQuery 实测头部 / 内容 / 底部三段自然高再分配滚动视口(无项数 × 定高的估算);间距全部内收为各段自身 padding,实测无需常量补偿;窗口变化(旋转 / 分屏)自动重测
-
重建边界:只有结构位翻转(布局互换、加载圈出现、行结构变化、项身份更替)整根重建;文字 / 颜色 / 禁用等纯属性变化原地更新,插槽内部状态与横向滚动位置不受无关更新影响
已知限制
- Web 端焦点圈定、入口恢复、最上层键盘所有权与背景隔离由 n-popup 统一管理;逻辑回归已通过,辅助功能朗读仍需真机验证
- 拖拽关闭开启时,头部(把手 + 标题区)是拖拽手势区,头部内长文本的触摸滚动让位于拖拽;需要头部滚动的场景关闭 drag-close
- 微信
share/feedback等能力无完成回调,组件不会自动收起,结果由页面原生流程接管 - 尚未完成的验收项见工作区验收记录文档(真机微信能力回调、系统最大字体、安全区机型等)