
Vant 4 ActionSheet 动作面板完全指南从基础用法到源码级原理【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant底部弹起的动作面板ActionSheet是移动端交互中最高频的组件之一用于在用户触发操作时展示一组与当前情境相关的选项。本文以 Vant 4 的 ActionSheet 组件文档为主体结合 组件实现源码、类型定义、样式源码 与 单元测试系统讲解其引入方式、全部 Props / Action 数据结构 / Events / Slots、主题定制方案并深入到 Popup 底层的关闭拦截与 z-index 机制。读完本文你将能独立完成 ActionSheet 的接入、二次封装与深度定制。组件定位与引入ActionSheet 是一个从底部弹起的模态面板包含与当前情境相关的多个操作选项典型场景包括分享菜单、操作菜单、筛选菜单等。Vant 4 支持按需引入与全量引入。推荐的方式是通过app.use全局注册组件import { createApp } from vue; import { ActionSheet } from vant; const app createApp(); app.use(ActionSheet);注册完成后即可在模板中以van-action-sheet标签使用。更多注册方式如按需引入样式、自动按需引入插件等可参考 组件注册文档。组件入口文件 index.ts 通过withInstall包装组件并默认导出同时导出了actionSheetProps与ActionSheetProps、ActionSheetAction、ActionSheetThemeVars等类型并声明了VanActionSheet全局组件类型。代码演示六种实战场景基础用法动作面板通过actions属性定义选项它是一个由对象构成的数组每个对象对应一个选项即文档中的一列对象支持的字段见后文「Action 数据结构」表格。van-cell is-link title基础用法 clickshow true / van-action-sheet v-model:showshow :actionsactions selectonSelect /import { ref } from vue; import { showToast } from vant; export default { setup() { const show ref(false); const actions [ { name: 选项一 }, { name: 选项二 }, { name: 选项三 }, ]; const onSelect (item) { // 默认情况下点击选项时不会自动收起 // 可以通过 close-on-click-action 属性开启自动收起 show.value false; showToast(item.name); }; return { show, actions, onSelect, }; }, };这里通过v-model:show双向绑定面板显隐通过select监听选项点击。需要注意的是默认点击选项不会自动收起需要手动将show置为false或直接开启close-on-click-action属性。从源码看选项被渲染为原生button元素ActionSheet.tsx点击处理逻辑为const onClick () { if (disabled || loading) return; // 禁用/加载中直接忽略点击 if (callback) callback(action); // 优先执行选项自身的 callback if (props.closeOnClickAction) updateShow(false); // 按需自动关闭 nextTick(() emit(select, action, index)); // 再触发 select 事件 };可见callback与select事件都会触发且callback先于select执行loading或disabled状态下的点击会被直接拦截。展示图标为选项配置icon字段即可在文字左侧展示图标图标名称与 Vant Icon 组件 的name属性一致v4.8.6 起支持van-cell is-link title展示图标 clickshow true / van-action-sheet v-model:showshow :actionsactions selectonSelect /import { ref } from vue; import { showToast } from vant; export default { setup() { const show ref(false); const actions [ { name: 选项一, icon: cart-o }, { name: 选项二, icon: shop-o }, { name: 选项三, icon: star-o }, ]; const onSelect (item) { show.value false; showToast(item.name); }; return { show, actions, onSelect, }; }, };源码中通过renderIcon渲染van-icon元素ActionSheet.tsx图标尺寸与间距分别由 CSS 变量--van-action-sheet-item-icon-size默认 18px与--van-action-sheet-item-icon-margin-right默认var(--van-padding-xs)控制。展示取消按钮设置cancel-text属性后底部会出现取消按钮点击后关闭面板并触发cancel事件van-action-sheet v-model:showshow :actionsactions cancel-text取消 close-on-click-action cancelonCancel /import { ref } from vue; import { showToast } from vant; export default { setup() { const show ref(false); const actions [ { name: 选项一 }, { name: 选项二 }, { name: 选项三 }, ]; const onCancel () showToast(取消); return { show, actions, onCancel, }; }, };源码中取消按钮通过renderCancel渲染ActionSheet.tsx只有存在slots.cancel或cancelText时才渲染结构上先渲染一个bem(gap)间隔块使用--van-action-sheet-cancel-padding-color背景色再渲染取消按钮。点击后调用onCancel同时发出update:showfalse与cancel事件。展示描述信息通过description属性在选项列表顶部展示描述文字通过选项的subname字段在选项文字下方展示二级说明van-action-sheet v-model:showshow :actionsactions cancel-text取消 description这是一段描述信息 close-on-click-action /import { ref } from vue; export default { setup() { const show ref(false); const actions [ { name: 选项一 }, { name: 选项二 }, { name: 选项三, subname: 描述信息 }, ]; return { show, actions, }; }, };渲染顺序上描述信息description位于标题与选项列表之间ActionSheet.tsx其下方有 hairline 分隔线index.lesssubname则作为选项内的独立行渲染bem(subname)位于name之下。选项状态着色、禁用与加载可以通过loading与disabled将选项设置为加载或禁用状态通过color自定义选项文字颜色van-action-sheet v-model:showshow :actionsactions cancel-text取消 close-on-click-action /import { ref } from vue; export default { setup() { const show ref(false); const actions [ { name: 着色选项, color: #ee0a24 }, { name: 禁用选项, disabled: true }, { name: 加载选项, loading: true }, ]; return { show, actions, }; }, };三种状态的实现细节color直接以内联style{{ color }}作用于选项按钮ActionSheet.tsx测试用例 index.spec.ts 验证了item.style.color会被正确设置。loading选项内容被替换为Loading加载图标renderActionContent中优先判断action.loading点击被忽略。disabled添加van-action-sheet__item--disabled类名样式上cursor: not-allowed且点击时无按压背景变化index.less。测试用例明确断言点击 loading 或 disabled 选项不会触发 select 事件index.spec.ts与源码逻辑一致。自定义面板通过默认插槽可以完全自定义面板内容同时可用title属性展示顶部标题栏van-action-sheet v-model:showshow title标题 div classcontent内容/div /van-action-sheet style .content { padding: 16px 16px 160px; } /style标题栏renderHeader仅在传入title时渲染右侧同时渲染关闭图标受closeable控制默认显示。默认插槽内容渲染在选项列表之后slots.default?.()因此使用自定义面板时通常无需传入actions。官方 demo/index.vue 中自定义面板示例使用padding: 16px 16px 160px预留底部空间避免内容贴底。API 详解Props 总览参数说明类型默认值v-model:show是否显示动作面板booleanfalseactions面板选项列表ActionSheetAction[][]title顶部标题string-cancel-text取消按钮文字string-description选项上方的描述信息string-closeable是否显示关闭图标booleantrueclose-icon关闭图标名称或图片链接等同于 Icon 组件的 name 属性stringcrossduration动画时长单位秒设置为 0 可以禁用动画number | string0.3z-index将面板的 z-index 层级设置为一个固定值number | string2000round是否显示圆角booleantrueoverlay是否显示遮罩层booleantrueoverlay-class自定义遮罩层类名string | Array | object-overlay-style自定义遮罩层样式object-lock-scroll是否锁定背景滚动booleantruelazy-render是否在显示弹层时才渲染节点booleantrueclose-on-popstate是否在页面回退时自动关闭booleantrueclose-on-click-action是否在点击选项后关闭booleanfalseclose-on-click-overlay是否在点击遮罩层后关闭booleantruesafe-area-inset-bottom是否开启底部安全区适配booleantrueteleport指定挂载的节点等同于 Teleport 组件的 to 属性string | Element-before-close关闭前的回调函数返回false可阻止关闭支持返回 Promise(action: string) boolean | Promiseboolean-从源码 ActionSheet.tsx 看组件自身的 props 定义十分精简export const actionSheetProps extend({}, popupSharedProps, { title: String, round: truthProp, actions: makeArrayPropActionSheetAction(), closeIcon: makeStringProp(cross), closeable: truthProp, cancelText: String, description: String, closeOnPopstate: truthProp, closeOnClickAction: Boolean, safeAreaInsetBottom: truthProp, });其中popupSharedProps定义于 popup/shared.ts贡献了show、zIndex、overlay、duration、teleport、lockScroll、lazyRender、beforeClose、overlayClass、overlayStyle、closeOnClickOverlay等通用弹层属性。ActionSheet 通过pick(props, popupInheritKeys)将这些属性透传给内部的 Popup 组件自身只负责渲染标题、描述、选项列表与取消按钮。几个值得注意的默认值细节closeOnClickAction默认false即点击选项默认不收起与基础用法演示中的注释一致round、overlay、closeable、lock-scroll、lazy-render、close-on-popstate、safe-area-inset-bottom均默认truez-index默认值是动态的文档标注为2000Popup 的open逻辑中若未显式传入zIndex会通过useGlobalZIndex()取全局递增层级保证新打开的面板始终位于已打开弹层之上Popup.tsx。Action 数据结构actions数组中的每个对象支持以下字段键名说明类型name标题stringsubname二级标题stringcolor选项文字颜色stringiconv4.8.6选项图标名称或图片链接stringclassName为对应列添加额外的 classstring | Array | objectloading是否为加载状态booleandisabled是否为禁用状态booleancallback点击时触发的回调函数action: ActionSheetAction对应的 TypeScript 定义直接写在 ActionSheet.tsx 中export type ActionSheetAction { icon?: string; name?: string; color?: string; subname?: string; loading?: boolean; disabled?: boolean; callback?: (action: ActionSheetAction) void; className?: unknown; };className会与默认类名van-action-sheet__item合并到按钮的 class 上callback与select事件可以同时使用二者都会在点击时触发。Events事件名说明回调参数select点击选项时触发禁用或加载状态下不会触发action: ActionSheetAction, index: numbercancel点击取消按钮时触发-open打开面板时触发-close关闭面板时触发-opened打开面板且动画结束后触发-closed关闭面板且动画结束后触发-click-overlay点击遮罩层时触发event: MouseEvent其中open、close、opened、closed、click-overlay均透传自内部 Popupselect与cancel由 ActionSheet 自身发出。测试用例验证了select的回调参数形如[{ name: Option }, 0]选项对象 索引index.spec.ts。Slots名称说明参数default自定义面板的展示内容-description自定义描述文案-cancel自定义取消按钮内容-action自定义选项内容{ action: ActionSheetAction, index: number }description插槽存在时优先于description属性渲染renderDescription中slots.description ? slots.description() : props.descriptionaction插槽为每个选项提供完全自定义渲染的能力且loading状态仍优先于插槽渲染renderActionContent先判断action.loading。类型定义组件导出以下类型定义便于在业务代码中获得完整的类型提示import type { ActionSheetProps, ActionSheetAction } from vant;此外 index.ts 还导出了ActionSheetThemeVars定义于 types.ts用于描述全部主题 CSS 变量的类型。主题定制样式变量组件在 index.less 中通过:root, :host声明了全部 CSS 变量默认值如下名称默认值描述--van-action-sheet-max-height80%面板最大高度--van-action-sheet-header-height48px标题栏高度--van-action-sheet-header-font-sizevar(--van-font-size-lg)标题字号--van-action-sheet-description-colorvar(--van-text-color-2)描述文字颜色--van-action-sheet-description-font-sizevar(--van-font-size-md)描述字号--van-action-sheet-description-line-heightvar(--van-line-height-md)描述行高--van-action-sheet-item-backgroundvar(--van-background-2)选项背景色--van-action-sheet-item-font-sizevar(--van-font-size-lg)选项字号--van-action-sheet-item-line-heightvar(--van-line-height-lg)选项行高--van-action-sheet-item-text-colorvar(--van-text-color)选项文字颜色--van-action-sheet-item-disabled-text-colorvar(--van-text-color-3)禁用选项文字颜色--van-action-sheet-item-icon-size18px选项图标尺寸--van-action-sheet-item-icon-margin-rightvar(--van-padding-xs)选项图标右间距--van-action-sheet-subname-colorvar(--van-text-color-2)二级标题颜色--van-action-sheet-subname-font-sizevar(--van-font-size-sm)二级标题字号--van-action-sheet-subname-line-heightvar(--van-line-height-sm)二级标题行高--van-action-sheet-close-icon-size22px关闭图标尺寸--van-action-sheet-close-icon-colorvar(--van-gray-5)关闭图标颜色--van-action-sheet-close-icon-padding0 var(--van-padding-md)关闭图标内边距--van-action-sheet-cancel-text-colorvar(--van-gray-7)取消按钮文字颜色--van-action-sheet-cancel-padding-topvar(--van-padding-xs)取消按钮上间距--van-action-sheet-cancel-padding-colorvar(--van-background)取消按钮间隔背景色--van-action-sheet-loading-icon-size22px加载图标尺寸使用方式通过 ConfigProvider 组件 在应用根部注入主题变量或直接在组件上以 style / class 覆盖。由于变量多引用 Vant 的全局设计令牌如--van-text-color-2、--van-background-2定制时可以与全局主题保持天然一致。源码级原理底层 Popup 与关闭拦截ActionSheet 的骨架实际是固定positionbottom的 Popup 组件ActionSheet.tsx因此继承了 Popup 的完整能力before-close 拦截Popup 的close()通过callInterceptor(props.beforeClose, { done })执行关闭前回调Popup.tsx回调返回false或 reject 的 Promise 时面板不会关闭可用于二次确认关闭表单校验未通过不允许关闭等场景遮罩层点击onClickOverlay先发出click-overlay事件再依据closeOnClickOverlay决定是否关闭Popup.tsx懒渲染lazyRender默认开启面板首次显示前不渲染 DOM。测试用例验证了关闭懒渲染后.van-action-sheet__content会立即存在于 DOMindex.spec.ts安全区适配safe-area-inset-bottom默认开启为面板根节点添加van-safe-area-bottom类测试用例同样覆盖了该行为index.spec.tsteleport 挂载teleport属性将整个面板挂载到指定节点测试中挂载到自定义div后可正常找到面板 DOMindex.spec.ts。从布局结构看面板根节点使用display: flex; flex-direction: column; max-height: var(--van-action-sheet-max-height)选项区域.van-action-sheet__content为flex: 1 auto并支持overflow-y: auto滚动index.less因此当选项过多时内容区会自动滚动头部、描述与取消按钮保持固定。小结ActionSheet 是 Vant 4 中轻封装、重继承组件的典型代表自身仅约 20 行 props 定义ActionSheet.tsx却通过组合 Popup 获得了遮罩、动效、锁滚动、安全区、teleport、before-close 拦截等完整弹层能力。使用时记住三个关键点即可覆盖绝大多数场景选项用actions数组描述、点击行为靠select/callback/close-on-click-action组合控制、视觉定制优先走 CSS 变量。若需要深度改造可直接阅读 组件源码 与其 单元测试测试用例覆盖了事件、状态、插槽、懒渲染等全部核心行为是理解组件契约的最佳参考。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考