Vant SubmitBar 提交订单栏组件实战指南:金额展示、状态控制与主题定制
2026/9/13 6:44:15 网站建设 项目流程

Vant SubmitBar 提交订单栏组件实战指南:金额展示、状态控制与主题定制

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

SubmitBar 是 Vant 移动端组件库中专门用于结算场景的底部操作栏组件,它负责在页面底部固定展示订单金额与提交按钮,是电商下单、购物车结算等流程中的核心交互入口。本文以 SubmitBar 中文文档 为主线,结合组件源码与测试用例,系统讲解该组件的引入方式、全部 Props / Events / Slots 用法、金额格式化与占位元素的底层实现原理,以及通过 CSS 变量进行主题定制的方法。

介绍

SubmitBar 提交订单栏用于展示订单金额与提交订单。它通常固定在页面底部,左侧展示金额(支持自定义货币符号、小数位数与文案),右侧展示一个提交按钮,并可在订单栏上方插入提示文案(如"你的收货地址不支持配送"),是 Vant 中处理结算确认场景的标准组件。

组件源码位于 SubmitBar.tsx,入口通过withInstall包装为可全局注册的插件,并在vue模块上声明了VanSubmitBar全局组件类型(见 index.ts)。

引入与注册

通过以下方式来全局注册组件,更多注册方式请参考 组件注册。

import { createApp } from 'vue'; import { SubmitBar } from 'vant'; const app = createApp(); app.use(SubmitBar);

注册后即可在模板中直接使用<van-submit-bar>标签(kebab-case写法),并自动获得完整的类型提示。

代码演示

基础用法

最基本的用法是传入以"分"为单位的金额price与按钮文字button-text,并通过@submit监听点击提交事件:

<van-submit-bar :price="3050" button-text="提交订单" @submit="onSubmit" />
import { showToast } from 'vant'; export default { setup() { const onSubmit = () => showToast('点击按钮'); return { onSubmit, }; }, };

price的单位是,组件内部会自动将其格式化为"元"展示:3050分会渲染为¥30.50(详见下文"金额格式化原理"小节)。默认货币符号为¥,可通过currency属性替换。

禁用状态

禁用状态下按钮置灰,且不会触发submit事件。可配合tiptip-icon在订单栏上方给出禁用原因提示:

<van-submit-bar disabled :price="3050" button-text="提交订单" tip="你的收货地址不支持配送" tip-icon="info-o" @submit="onSubmit" />

加载状态

加载状态下按钮显示为加载中动画,同样不会触发submit事件,通常用于提交请求进行中的场景,防止重复提交:

<van-submit-bar loading :price="3050" button-text="提交订单" @submit="onSubmit" />

高级用法

通过插槽插入自定义内容:default插槽可在金额左侧放置自定义元素(如全选 Checkbox),tip插槽可往提示文案中追加额外内容(如"修改地址"链接):

<van-submit-bar :price="3050" button-text="提交订单" @submit="onSubmit"> <van-checkbox v-model="checked">全选</van-checkbox> <template #tip> 你的收货地址不支持配送, <span @click="onClickLink">修改地址</span> </template> </van-submit-bar>
import { showToast } from 'vant'; export default { setup() { const onSubmit = () => showToast('点击按钮'); const onClickLink = () => showToast('修改地址'); return { onSubmit, onClickLink, }; }, };

上述演示在仓库中的完整实现可参考 demo/index.vue,其中还包含中英文文案的useTranslate切换逻辑。

API

Props

参数说明类型默认值
price金额(单位分)number-
decimal-length金额小数点位数number | string2
label金额左侧文案string合计:
suffix-label金额右侧文案string-
text-align金额文案对齐方向,可选值为leftstringright
button-text按钮文字string-
button-type按钮类型stringdanger
button-color自定义按钮颜色string-
tip在订单栏上方的提示文案string-
tip-icon提示文案左侧的图标名称或图片链接,等同于 Icon 组件的 name 属性string-
currency货币符号string¥
disabled是否禁用按钮booleanfalse
loading是否显示将按钮显示为加载中状态booleanfalse
safe-area-inset-bottom是否开启底部安全区适配booleantrue
placeholder是否在标签位置生成一个等高的占位元素booleanfalse

各 Props 在源码中的声明可对照 SubmitBar.tsx 中的submitBarProps

  • currencybuttonTypedecimalLength分别使用makeStringProp('¥')makeStringProp<ButtonType>('danger')makeNumericProp(2)生成带默认值的类型化 prop;
  • safeAreaInsetBottom使用truthProp生成默认true的布尔 prop;
  • textAlign通过PropType<SubmitBarTextAlign>限定为'left' | 'right'字面量联合类型。

补充说明:button-type的合法取值与 Button 组件一致,即default | primary | success | warning | danger,该联合类型定义于 button/types.ts。组件源码中该值会直接透传给内部渲染的Button组件。

Events

事件名说明回调参数
submit按钮点击事件回调-

submit事件由onClickButton通过emit('submit')触发(见 SubmitBar.tsx)。注意:disabledloading状态下该事件不会被触发——因为此时内部 Button 组件本身处于禁用/加载态,点击不会冒泡出回调。

Slots

名称说明
default自定义订单栏左侧内容
button自定义按钮
top自定义订单栏上方内容
tip提示文案中的额外内容

插槽在渲染结构中的位置与优先级:top渲染在整栏最上方;tiptip文案共同渲染在提示区域;button插槽优先于默认按钮渲染——当传入button插槽时,组件会直接渲染插槽内容而忽略内部Button(见 SubmitBar.tsx)。

类型定义

组件导出以下类型定义:

import type { SubmitBarProps, SubmitBarTextAlign } from 'vant';

其中SubmitBarPropssubmitBarProps通过ExtractPropTypes推导得出,SubmitBarTextAlign'left' | 'right'。此外,组件还从 types.ts 导出了SubmitBarThemeVars,用于 ConfigProvider 场景下的主题变量类型约束。

深入源码:金额格式化与渲染结构

金额格式化原理

组件在renderText中完成分到元的格式化(见 SubmitBar.tsx):

const pricePair = (price / 100).toFixed(+decimalLength).split('.'); const decimal = decimalLength ? `.${pricePair[1]}` : '';

其关键逻辑如下:

  1. 单位换算price(分)除以 100 得到元的数值;
  2. 定点精度:通过toFixed(+decimalLength)decimal-length指定的小数位数截断(注意+decimalLength的隐式类型转换,因为该 prop 类型为number | string);
  3. 整数/小数分离:以.为分隔符拆分为整数部分pricePair[0]与小数部分;
  4. 无小数模式:当decimalLength0(数字 0 为 falsy)时只渲染整数部分,省略小数点与小数位。

最终渲染结构为:label(默认"合计:")+currency(货币符号)+ 整数部分 + 小数部分 + 可选suffixLabel。其中整数部分会单独使用.van-submit-bar__price-integer类,从而应用更大的字号与--van-price-font字体族,实现电商风格的大号整数价格视觉效果。

该行为在 test/index.spec.ts 中有明确验证:price=111decimalLength=1时渲染¥11.1,切换为decimalLength=0时渲染¥11

组件 DOM 结构与插槽渲染顺序

renderSubmitBar(见 SubmitBar.tsx)可以看出,组件的实际 DOM 结构为:

.van-submit-bar(fixed 定位,默认附带 .van-safe-area-bottom) ├── #top 插槽 ├── .van-submit-bar__tip(tip 文案 + tip-icon 图标 + #tip 插槽,仅在 tip 或 #tip 存在时渲染) └── .van-submit-bar__bar ├── #default 插槽(金额左侧内容) ├── .van-submit-bar__text(label + price + suffix-label) └── Button 组件 / #button 插槽

两点细节值得注意:

  • 提示区按需渲染renderTip只有在slots.tiptip文案存在时才输出.van-submit-bar__tip节点(见 SubmitBar.tsx),避免无提示时产生多余的空元素;
  • 金额区按需渲染renderText仅在price为数字类型时输出金额文本。测试用例should not render label without price验证了这一点——不传price时,即使设置了label也不会渲染"合计"文案(见 test/index.spec.ts)。

placeholder 占位元素与 safe-area 适配

SubmitBar 默认position: fixed固定在底部(见 index.less),会遮挡页面底部内容。为此组件提供了两种解决方案:

  1. 占位元素:开启placeholder后,组件通过usePlaceholder(use-placeholder.tsx)在标签位置生成一个等高的占位<div>,把真实栏"顶"到正常文档流中,同时保持固定定位。占位高度由useHeight(use-height.ts)通过getBoundingClientRect实时测量:

    • 开启安全区时,系统在页面加载初期可能返回不准确的高度,因此组件会延迟 3 次(100ms/200ms/300ms)重新测量;
    • 弹层(popup)重开时高度可能为 0,会通过onPopupReopen在 nextTick 后重新测量;
    • 窗口尺寸变化时(windowWidth/windowHeight变化)也会重新测量。

    测试用例should render placeholder element when using placeholder prop通过mockGetBoundingClientRect({ height: 50 })验证了占位元素的高度逻辑(见 test/index.spec.ts)。

  2. 底部安全区safe-area-inset-bottom默认开启(true),此时组件根节点会附带van-safe-area-bottom类,配合 Vant 全局样式中的env(safe-area-inset-bottom)适配 iPhone 等全面屏设备的底部 Home 指示条区域。测试用例验证了关闭该属性后.van-safe-area-bottom类不会出现(见 test/index.spec.ts)。

主题定制

样式变量

组件提供了下列 CSS 变量,可用于自定义样式。使用方法请参考 ConfigProvider 组件,即通过<van-config-provider :theme-vars="...">包裹或直接在:root中覆盖。

名称默认值描述
--van-submit-bar-height50px-
--van-submit-bar-z-index100-
--van-submit-bar-backgroundvar(--van-background-2)-
--van-submit-bar-button-width110px-
--van-submit-bar-price-colorvar(--van-danger-color)-
--van-submit-bar-price-font-sizevar(--van-font-size-sm)-
--van-submit-bar-price-integer-font-size20px-
--van-submit-bar-price-fontvar(--van-price-font)-
--van-submit-bar-text-colorvar(--van-text-color)-
--van-submit-bar-text-font-sizevar(--van-font-size-md)-
--van-submit-bar-tip-paddingvar(--van-padding-xs) var(--van-padding-sm)-
--van-submit-bar-tip-font-sizevar(--van-font-size-sm)-
--van-submit-bar-tip-line-height1.5-
--van-submit-bar-tip-colorvar(--van-orange-dark)-
--van-submit-bar-tip-backgroundvar(--van-orange-light)-
--van-submit-bar-tip-icon-size12px-
--van-submit-bar-button-height40px-
--van-submit-bar-padding0 var(--van-padding-md)-

这些变量在 index.less 中有完整的声明与消费位置,可直接对照查看:

  • 根节点.van-submit-bar使用z-indexbackground
  • 提示区.van-submit-bar__tip使用tip-paddingtip-colortip-font-sizetip-line-heighttip-background,图标.van-submit-bar__tip-icon使用tip-icon-size
  • 主栏.van-submit-bar__bar使用heightpaddingtext-font-size
  • 金额文本.van-submit-bar__text使用text-color,价格部分.van-submit-bar__price使用price-colorprice-font-size,整数部分__price-integer使用price-integer-font-sizeprice-font
  • 按钮.van-submit-bar__button使用button-widthbutton-height

典型定制示例——例如将主栏加高并改为蓝色按钮:

<van-config-provider :theme-vars="{ submitBarHeight: '56px', submitBarButtonWidth: '120px', submitBarBackground: '#ffffff', }" > <van-submit-bar :price="3050" button-text="提交订单" @submit="onSubmit" /> </van-config-provider>

由于SubmitBarThemeVars已导出类型,上述配置在 TypeScript 项目下可获得完整的字段提示与校验。

测试验证概览

组件测试用例位于 test/index.spec.ts,覆盖了本文涉及的大部分行为,可作为理解组件契约的补充参考:

  • 点击按钮触发submit事件;
  • disabled状态下不触发submit,且按钮快照正确;
  • price时不渲染label文案;
  • decimal-length变化时金额渲染随之变化;
  • text-align影响金额文本对齐;
  • safe-area-inset-bottom控制安全区类名;
  • button-color改变按钮颜色;
  • top/button插槽正确渲染;
  • placeholder生成等高占位元素。

小结

SubmitBar 组件以"分"为单位的金额输入、自动格式化展示、disabled/loading状态控制、四类插槽扩展与 CSS 变量主题定制构成了完整的结算栏能力闭环。实际开发中,建议结合placeholder或底部安全区适配解决固定定位遮挡问题,并优先通过default/button插槽满足个性化布局需求——例如在金额左侧追加运费说明、在按钮位置替换为自定义结算控件等。相关演示与测试用例可在仓库的 submit-bar 目录 中继续查阅。

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询