Skip to content

n-fab 悬浮动作按钮 ​

用于新建、客服、分享等常驻操作入口。组件内部处理四角定位、四向菜单、拖拽、边缘吸附、遮罩与禁用,调用者只需配置数据、属性和插槽。

平台兼容性 ​

App H5 微信小程序 支付宝小程序 百度小程序 头条小程序 QQ小程序
√ √ √ × × × ×

如何调用 ​

html
<n-fab v-model:active="active" :list="actions" @click="onAction" />
ts
import { ref } from "vue";
import type { NFabItem } from "@/uni_modules/new-ui/components/n-fab/props";
const active = ref(false);
const actions: NFabItem[] = [
 { icon: "star", label: "收藏" },
 { abbr: "赞", label: "点赞", textSize: 22, background: "#f59e0b" },
 { src: "/static/avatar.png", label: "联系人", imageWidth: 32, imageHeight: 32, imageRadius: 8 }
];
function onAction(detail: { index: number }): void {
 uni.showToast({ title: `点击 ${detail.index}`, icon: "none" });
}

状态与定位 ​

active 为受控值,使用官方 v-model:active。点击主按钮请求切换状态;点击菜单项先触发 click({index}),再请求收起;遮罩仅在 maskClosable=true 时请求收起。父组件不回写更新请求时,状态保持原值。无菜单或 expandable=false 时,主按钮直接触发 click({index:-1})。

position 始终相对可用视口定位主按钮,菜单不会挤动主按钮;Web 计入导航栏和底部栏的视口偏移。direction 单独控制展开方向;请选择有足够空间的方向,例如右下角向上或向左。组件不会擅自改变指定方向。

draggable=auto 拖动后吸附最近的左右边缘;free 保留松手位置;none 关闭拖动。实际位移超过 10px 才进入拖拽,轻触不会触发吸附;取消手势保留当前位置,不吸附。Web 同时支持鼠标拖动。按钮尺寸来自组件内部的真实布局测量,调用者不需要查询元素、监听滚动或手动刷新。尺寸、角位、间距及窗口变化后重新按配置定位。gap 顺序为上、右、下、左,每项接受数字或 px/rpx 字符串;数字及无单位字符串按 px 解释。定位和吸附共用官方单位换算后的像素值,rpx 遵循平台转换规则和宿主的单位配置。窗口变化及隐藏后恢复时刷新视口并重新取转换结果;底部需要避开系统手势区域时增大第三项。

展开时从遮罩、菜单项、标签和自定义菜单滑动均在组件共同根节点处理,不会滚动底层页面;Web 在遮罩可见时同时拦截组件区域内的滚轮。收起后底层页面正常滚动。

内容与样式 ​

圆内内容优先级为 icon > src > abbr,label 是朝屏幕中心一侧的标签。逐项颜色、字号、图片宽高与圆角直接写入列表数据。业务字段不同可配置 nameKey/srcKey/textKey,默认分别为 icon/src/label;组件内部完成映射,item 插槽仍取得原始数据及其业务附加字段。圆内缩写独立使用 abbr。例如 { text: "联系客服", abbr: "客" } 配合 textKey="text",侧边显示“联系客服”,圆内只显示“客”;不会把侧边标题作为缩写。background 同时作用于主按钮和没有独立背景的菜单项,支持实色及 linear-gradient(to right, #f53423, #f67f48);渐变方向请使用关键词。

NFabLength 即 number | string。size=-1 与 iconSize=-1 使用主题令牌,实际默认分别为 56px、16px;显式尺寸覆盖令牌;主按钮尺寸、逐项字号、图片宽高和圆角均接受数字或 px/rpx 字符串,例如 icon-size="32rpx"。尺寸字段中的 -1 表示采用主题值,圆角可为 0;边距允许 0,不采用 -1。customClass/customStyle 作用于组件根容器,适合设置 CSS 变量;内部按钮背景请用 background,不依赖样式继承。

插槽 ​

default 替换整区菜单,trigger 替换主按钮内容,item 替换列表项圆内内容。自定义内容不叠加旋转。default 菜单中的点击与收起由插槽内容决定:

disabled 同时禁用内置内容与所有插槽,组件在交互区域拦截触摸和点击,调用者无需再给插槽按钮绑定禁用属性。插槽内容具有独立的层叠边界,内部设置 z-index 不会越过组件的禁用交互层。禁用保留 active,已展开的菜单继续显示并降低透明度;恢复后保持原展开状态。列表项 disabled 同样覆盖该项的 item 插槽;整体与单项同时禁用时不重复降低透明度。

html
<n-fab v-model:active="active">
 <template #default>
  <n-button text="新建" @click="active = false" />
 </template>
 <template #trigger>
  <n-icon name="edit-fill" :size="24" color="#ffffff" />
 </template>
</n-fab>

微信开放能力 ​

FAB 可作为客服、分享或授权入口。开放能力是可选的原生按钮能力,默认 openType="" 不启用;App 和 Web 不编译该能力层。主按钮和列表项均可配置能力参数,支持的平台值与按钮一致:contact、share、getPhoneNumber、getRealtimePhoneNumber、getUserInfo、launchApp、openSetting、chooseAvatar、agreePrivacyAuthorization、feedback、liveActivity。除 share/feedback 使用平台自身流程,其余能力均透传对应原生回调和原生 error。原生能力按钮只在微信端编译,点击仍经过组件的 click/change 逻辑;普通轻触保留能力,实际拖动后屏蔽该次点击。禁用时清空 open-type 并拦截组件操作。

API ​

属性 ​

属性 类型 默认值 说明
list NFabItem[] [] 菜单项列表(NFabItem);无 default 插槽且为空数组时为单按钮模式,点击主按钮触发 click({index:-1})
nameKey string icon 菜单数据的图标字段名;映射在组件内完成,不修改原始数据
srcKey string src 菜单数据的图片地址字段名
textKey string label 菜单数据的侧边标签字段名;圆内缩写独立使用 abbr 字段
active boolean false 展开状态,v-model:active 双向绑定;展开时显示菜单与遮罩,收起时主按钮图标复位
type NFabType primary 主按钮色调:primary / success / warning / error / info,菜单项默认跟随
background string 主按钮与菜单项背景,支持实色及关键词方向的 linear-gradient;菜单项可逐项覆盖
position NFabPosition right-bottom 停驻角位:right-bottom / left-bottom / right-top / left-top;展开方向须留有空间
direction NFabDirection top 菜单展开方向:top 向上 / bottom 向下(列),left 向左 / right 向右(行)
draggable NFabDraggable auto 拖拽模式:auto 可拖并自动吸附左右边缘 / free 可拖停在松手处 / none 固定
gap NFabLength[] [16, 16, 16, 16] 与视口四边的间距,数字为 px,字符串支持 px/rpx;顺序 [上, 右, 下, 左];悬浮在底部时注意加大下边距避开手势条
size NFabLength -1 主按钮与菜单项直径:数字或 px/rpx 字符串;-1 使用主题尺寸(默认 56px)
iconSize NFabLength -1 主按钮与菜单项图标尺寸:数字或 px/rpx 字符串;-1 使用主题尺寸(默认 16px)
inactiveIcon string plus 收起态主按钮图标名
activeIcon string close 展开态主按钮图标名
iconColor string 主按钮与菜单项的图标/文字颜色覆盖(空 = 白色)
expandable boolean true 点击主按钮是否展开菜单;false 时主按钮为普通动作按钮,点击触发 click(-1)
disabled boolean false 禁用整个组件(含插槽内容):保色相降透明,点击与拖拽被拦截,保留 active 受控值
zIndex number 99 悬浮层级;低于弹窗(1000 起),遮罩取 zIndex - 10
mask boolean true 展开时显示遮罩弱化页面
maskClosable boolean false 点击遮罩请求收起菜单
maskBackground string 遮罩背景色;空使用主题遮罩色
openType string 主按钮微信开放能力(仅微信端生效),如 contact / share / getPhoneNumber;非空时主按钮点击走原生按钮承接
appParameter string 主按钮 open-type=launchApp 时打开 App 的参数
lang string en 主按钮 open-type=getUserInfo 时返回信息的语言,合法值 zh_CN / zh_TW / en
sessionFrom string 主按钮 open-type=contact 时会话来源
sendMessageTitle string 主按钮 open-type=contact 时会话卡片标题
sendMessagePath string 主按钮 open-type=contact 时会话卡片点击进入的小程序路径
sendMessageImg string 主按钮 open-type=contact 时会话卡片图片
showMessageCard boolean false 主按钮 open-type=contact 时显示会话内消息卡片
phoneNumberNoQuotaToast boolean false open-type=getPhoneNumber 失败时是否弹出原生提示,仅微信端生效
customClass string 挂到根节点的额外 class(类须在组件样式表内定义,页面 class 打不进组件)
customStyle string 根节点行内样式

事件 ​

事件名 说明 回调参数
click 点击菜单项或单按钮,主按钮 index 为 -1
change 请求改变展开状态 active: boolean
update:active 配合 v-model:active 回写受控状态 active: boolean
contact 微信客服回调 UniEvent
opensetting 微信设置回调 UniEvent
launchapp 微信打开 App 回调 UniEvent
getuserinfo 微信用户信息回调 UniEvent
getphonenumber 微信手机号回调 UniEvent
getrealtimephonenumber 微信实时手机号回调 UniEvent
chooseavatar 微信头像选择回调 UniEvent
agreeprivacyauthorization 微信隐私授权回调 UniEvent
createliveactivity 微信活动订阅回调 UniEvent
error 配置/测量失败为 NFabError;微信开放能力失败为原生事件 NFabError 或 UniEvent

插槽 ​

名称 说明 参数
default 整区自定义菜单;优先于 list —
trigger 自定义主按钮内容 —
item 自定义列表项圆内内容

数据与状态 ​

NFabItem 为 UTSJSONObject,可携带业务附加字段。默认渲染字段如下;nameKey/srcKey/textKey 分别替换图标、图片和侧边标签的字段名。

字段 类型 说明
icon / src / abbr string 圆内图标、图片、文字,按顺序取第一种非空内容
label string 侧边标签
background string 实色或渐变;空跟随主按钮 background/type
color string 圆内颜色;空跟随 iconColor,再回落主题填充前景色
iconSize number / string 图标尺寸,数字或 px/rpx 字符串;-1 跟随全局 iconSize
textSize / labelSize NFabLength 圆内缩写/侧边标签字号,数字或 px/rpx 字符串;-1 跟随主题
labelColor string 侧边标签颜色,空跟随主题
imageWidth / imageHeight NFabLength 图片宽高,数字或 px/rpx 字符串;-1 跟随主题
imageRadius NFabLength 图片圆角,数字或 px/rpx 字符串;-1 跟随主题,默认 0
disabled boolean 禁用该项,保持色相并降低透明度
openType / appParameter / lang / sessionFrom string 微信能力及参数
sendMessageTitle / sendMessagePath / sendMessageImg string 微信会话卡片参数
showMessageCard boolean 微信会话卡片开关
phoneNumberNoQuotaToast boolean 获取手机号失败时显示原生提示,默认 false

主题令牌 ​

CSS 变量均有同名 $n- SCSS 覆盖变量:

CSS 变量 默认值 作用
--n-fab-size 56px 主按钮及菜单项直径
--n-fab-icon-size 16px 主按钮及菜单图标尺寸
--n-fab-menu-gap 16px 菜单项间距及菜单与主按钮距离
--n-fab-label-size 16px 侧边标签字号
--n-fab-text-size 18px 圆内文字字号
--n-fab-image-width / --n-fab-image-height 28px 圆内图片宽高
--n-fab-image-radius 0px 圆内图片圆角
--n-fab-mask-color rgba(0,0,0,0.5) 遮罩色
--n-fab-shadow-color rgba(0,0,0,0.16) 主按钮投影,深色主题自动覆盖

实现说明 ​

机制 参考做法 本库做法及融合理由
菜单 任意默认插槽 / 配置列表 同时支持 default 与 list;item 用于单项内容定制
状态 active 受控 / 内部展开状态 统一官方 v-model:active;点击只发更新请求,视觉直接由受控值决定
定位 四角与四边间距 / rpx 左右及底部距离 主按钮固定、菜单独立绝对定位;gap 保留数字 px 并支持 px/rpx 字符串,官方换算结果同时用于定位和吸附
拖拽 auto/free/none / 跟手位移及边界限制 保留三态与视口限制;测量复用组件尺寸监听,微信采用带组件作用域的异步查询
内容 图标/图片/独立 abbr 缩写/可映射的侧边标签,逐项背景、字号与图片尺寸 保留 nameKey/srcKey/textKey 字段映射,在组件内归一为 icon/src/abbr/label;原始项交给插槽;textKey 只映射侧边标签,abbr 独立保存缩写;逐项颜色、字号和图片尺寸直接配置
单位 rpx 字号、图片尺寸与圆角 / 数字及字符串按钮尺寸 所有尺寸统一支持数字 px、px/rpx 字符串;不要求调用者查询窗口或换算单位
滚动拦截 共同根节点拦截触摸移动 根节点覆盖遮罩、内置菜单和自定义菜单;Web 同时处理遮罩可见时的滚轮,清理随组件卸载
背景 可设置实色及渐变 保留 background 与逐项覆盖;沿用库内按钮的背景变量、种类类名及节点 key,避开不支持的动态 background 简写
遮罩 mask、maskBackground、maskClosable=false 全部保留;层级始终为 zIndex-10,动态关闭立即撤销拦截
图标 活跃/非活跃图标切换 / 同一 plus 旋转 采用状态图标切换,不叠加旋转;默认字号采用 16px,尺寸均可配置
动画 250ms 缩放淡入淡出 菜单常驻,受控状态直接切换 transform/opacity;没有等待挂载的固定延时及额外卸载补偿
标签 左侧停驻标签在右,右侧停驻标签在左 四向均沿用侧边标签,拖到另一侧后自动调整对齐;不增加无参考的下方标签形态
微信能力 主按钮及逐项原生按钮参数、能力回调 保留可选能力层,回调及手机号提示参数对齐按钮;仅微信编译,真实拖拽与普通点击分开处理,原生错误完整透传
动态内容 图标/图片/缩写及可选标签 标签存在性在行节点 key 中表达,内置内容种类与背景种类在圆钮 key 中表达;内容插槽保留原始数据,避免无关内容切换重建
禁用 点击守卫 / 原生能力置空 / 自定义操作区交互覆盖层 主按钮与菜单内容使用独立内容容器隔离层叠,插槽自带 z-index 仍位于组件交互层之下;主按钮、整区菜单和单项均拦截交互,避免插槽子组件先执行回调;整体透明度统一处理,单项禁用不叠加降透明

验收覆盖 ​

功能面 回归检查
数据与 API 33 项属性、13 项事件与元数据/文档一致;字段映射保留原项、标题与 abbr 分离,非法配置反馈及恢复
定位与手势 四角 × 四向、auto/free/none、拖拽阈值及取消、禁用中断、尺寸变化、窗口变化与恢复、rpx 边距换算及吸附
内容与样式 图标/图片/abbr、逐项尺寸及颜色、背景种类切换、主题令牌、动态标签、default/trigger/item 插槽;展开后禁用、单项禁用、无重复透明度及恢复交互
滚动与事件 Web 实测菜单项/标签/遮罩/自定义菜单触摸及滚轮不穿透,收起后页面可滚动;微信校验原生 catchtouchmove 绑定及处理器注册;点击与拖拽区分、更新请求及微信回调透传
示例与交付 预览和复制代码保留字段及单位;复制内容可解析;元数据、规范审计、Web/微信开发者工具回归、Android/微信编译

微信自动化 SDK 的 CDP 触摸模拟会自行滚动页面,不能用它判定原生 catchtouchmove 是否拦截背景滚动;这一项尚未完成微信开发者工具的实际手势验证。

记录 · 思考 · 创作