Vuetify 按钮组件 v-btn 完全指南:从基础用法到全局配置与源码原理
2026/9/19 19:52:10 网站建设 项目流程

Vuetify 按钮组件 v-btn 完全指南:从基础用法到全局配置与源码原理

【免费下载链接】vuetify🐉 Vue Component Framework项目地址: https://gitcode.com/gh_mirrors/vu/vuetify

v-btn是 Vuetify 中替代原生 HTMLbutton的核心交互组件,以 Material Design 主题呈现,并提供了密度、尺寸、变体、加载状态、图标插槽等一整套可配置能力。本文以 buttons.md 文档为骨架,结合 VBtn.tsx 源码、VBtn.sass 样式与_variables.scss配置,系统讲解v-btn的用法、Props、Slots、默认值副作用(Defaults Side Effects)、全局配置、Aliasing、SASS 变量定制与无障碍实践,读完后你将能独立完成按钮的样式定制、状态管理与组件级默认值覆盖。

组件概览

v-btn替换标准 HTML 按钮并融入 Material Design 主题,支持大量选项。任何颜色辅助类(color helper class)都可以用来改变背景色或文字颜色。按钮最基本的形态包含大写文本、轻微阴影、悬停效果以及点击时的涟漪(ripple)效果。

在 VBtn.tsx 中,makeVBtnProps通过propsFactory聚合了来自多个 composables 的能力,包括makeDensityPropsmakeDimensionPropsmakeElevationPropsmakeRoundedPropsmakeSizePropsmakeVariantPropsmakeRouterPropsmakeBorderPropsmakeLocationProps等,这意味着按钮天然继承了 Vuetify 的通用设计系统。

API 一览

| 组件 | 说明 | | - | - | | v-btn | 主要组件 |

v-btn派生的组件族还包括 v-btn-group(按钮组)、v-btn-toggle(切换按钮组)等。

结构解剖(Anatomy)

官方推荐的v-btn内部元素排布方式是:

  • 文本放置在中心;
  • 视觉内容围绕容器文本放置。

| 元素 / 区域 | 说明 | | - | - | | 1. 容器(Container) | 除文本外,按钮容器通常还容纳一个 v-icon 组件 | | 2. 图标(Icon,可选) | 前置媒体内容,用于改善视觉上下文 | | 3. 文本(Text) | 用于显示文本和其他内联元素的内容区域 |

从渲染实现看,VBtn.tsx 会按顺序输出v-btn__prependv-btn__contentv-btn__append三个内部区域,这与文档推荐的结构完全对应。

基础用法

<v-btn>Button</v-btn>

这是仅包含文本的最简单用法。v-btn在 Vuetify 应用中被广泛用于导航、表单提交等场景,并能以多种方式设置样式。

Props 详解

Density(密度)

densityprop 用于控制按钮占用的垂直空间。可选值为defaultcomfortablecompact

<v-btn density="compact">Compact Button</v-btn> <v-btn density="comfortable">Comfortable Button</v-btn> <v-btn density="default">Default Button</v-btn>

源码层面,_variables.scss 定义了三档密度映射:

$button-density: ('default': 0, 'comfortable': -2, 'compact': -3) !default; $button-stacked-density: ('default': 0, 'comfortable': -4, 'compact': -6) !default; $button-icon-density: ('default': 3, 'comfortable': 0, 'compact': -2) !default;

_mixins.scss 中的button-densitymixin 根据密度档位计算height: calc(var(--v-btn-height) + 偏移量),即密度直接作用于按钮高度的 CSS 变量。

Size(尺寸)

sizeprop 控制按钮尺寸,并与密度联动缩放。默认值为undefined,实际等效于medium。可选值包括x-smallsmallmediumlargex-large

<v-btn size="large">Large Button</v-btn> <v-btn size="x-large">Extra Large Button</v-btn>

尺寸在样式层通过button-sizesmixin 实现(见 _mixins.scss):每个尺寸档位会生成--v-btn-size--v-btn-height两个 CSS 变量,并据此计算min-width(由width-ratio决定,默认16 / 9)与水平内边距(由padding-ratio决定,默认2.25)。

Block(块级)

block让按钮延伸至容器的全部可用宽度,适合创建横跨卡片或对话框全宽的按钮。

<v-btn block>Block Button</v-btn>

::: infoblock应用width: 100%,在 flex 容器中可能引发溢出问题。 :::

在 VBtn.tsx 中,block会为根元素追加v-btn--block类。

Rounded(圆角)

roundedprop 控制按钮的边框圆角半径。值为true时使用圆形圆角。

<v-btn rounded>Rounded Button</v-btn>

样式层默认提供了多个圆角档位:_variables.scss 中$button-icon-border-radius使用circle$button-rounded-border-radius使用xl

Elevation(阴影)

elevation属性提供最多 24 级阴影深度。默认情况下按钮处于 2dp 阴影。

<v-btn elevation="24">Elevated Button</v-btn>

注意,_variables.scss 中默认的$button-elevation映射为('default': 1, 'hover': 2, 'active': 1),按钮在不同状态下的阴影深度会自动切换。在 VBtn.tsx 中,isElevated计算属性表明:只有variant === 'elevated'且未禁用、未设置flatborder时按钮才处于 elevated 状态。

Ripple(涟漪)

ripple属性决定是否启用 v-ripple 指令。

<v-btn :ripple="false">No Ripple</v-btn>

在 VBtn.tsx 中,ripple的默认值为true,且类型支持Boolean | Object,可传入对象来精细控制涟漪行为;渲染时通过withDirectivesvRipple绑定到根元素(VBtn.tsx),并且当按钮为纯图标按钮(icon)时,涟漪会以center: true居中触发。

Variants(变体)

variantprop 让你轻松访问多种按钮风格。可选变体为:elevated(默认)、flattonaloutlinedtextplain

| 值 | 说明 | | - | - | |elevated| 通过阴影抬高按钮(默认) | |flat| 移除按钮阴影 | |tonal| 背景色为当前文本颜色的低透明度版本 | |outlined| 使用当前文本颜色应用细边框 | |text| 移除背景并移除阴影 | |plain| 移除背景,并在悬停前降低不透明度 |

<v-btn>elevated (default)</v-btn> <v-btn variant="flat">flat</v-btn> <v-btn variant="tonal">tonal</v-btn> <v-btn variant="outlined">outlined</v-btn> <v-btn variant="text">text</v-btn> <v-btn variant="plain">plain</v-btn>

源码中变体由makeVariantProps提供,默认值为elevated(VBtn.tsx),样式由tools.variantmixin 根据 _variables.scss 中定义的$button-variants映射生成,其中$button-plain-opacity: .62正是 plain 变体悬停前的不透明度来源。

Icon(图标按钮)

图标可以作为按钮的主要内容,常见于 v-toolbar 和 v-app-bar 组件中。

<v-btn icon="mdi-plus"></v-btn> <v-btn icon="mdi-account" size="x-small"></v-btn> <v-btn icon="mdi-calendar" size="x-large"></v-btn>

iconprop 支持Boolean | String | Function | Object(VBtn.tsx),即可以直接传图标名。当图标作为按钮内容时,VBtn.tsx 会在v-btn__content内自动渲染一个VIcon,同时设置v-btn--icon类以切换为方形容器、圆形圆角布局。

Loaders(加载状态)

使用loadingprop 可以告知用户正在处理中。默认行为是使用v-progress-circular组件,但可以通过loader插槽自定义。

<v-btn :loading="loading" @click="loading = !loading"> Button </v-btn>

从源码看(VBtn.tsx),当loading为真时,按钮内部渲染v-btn__loader区域,默认输出VProgressCircularindeterminatewidth="2");若loading传入字符串(如loading="error"),则作为加载指示器的颜色。同时根元素会带上aria-busy属性并将tabindex设为-1(VBtn.tsx),避免加载期间用户重复触发。

在工具栏内使用

一个常见场景是在 v-toolbar 或 v-app-bar 中配合icon属性使用v-btn,形成工具条上的操作图标。

Slots 详解

v-btn提供多个插槽,用于自定义由其 props 生成的内容或添加额外内容。

| 插槽 | 说明 | | - | - | | 1. Default | 默认插槽 | | 2. Prepend | 默认插槽之前的内容区域 | | 3. Append | 默认插槽之后的内容区域 | | 4. Loader | 当loadingtrue时显示的内容区域 |

插槽让你在继续享受易用 props 的同时,对v-btn内容拥有更大的定制控制力。

图标颜色

prepend-iconappend-iconprops 与对应的prependappend插槽结合使用时,可以放置一个自动注入指定图标的 v-icon。

<v-btn append-icon="mdi-account-circle" prepend-icon="mdi-check-circle"> <template v-slot:prepend> <v-icon color="success"></v-icon> </template> Button <template v-slot:append> <v-icon color="warning"></v-icon> </template> </v-btn>

实现细节上(VBtn.tsx),当存在prepend插槽时,组件会用VDefaultsProviderprependIcon注入到插槽内的VIcon上,使图标自动继承 prop 指定的图标名。

Spaced(间距)

默认情况下图标紧贴按钮内容,可以使用spacedprop 将它们分开。spaced取值可为startendboth

<v-btn prepend-icon="$prev" spaced="start">Previous</v-btn> <v-btn append-icon="$next" prepend-icon="$prev" spaced="both">Navigate</v-btn> <v-btn append-icon="$next" spaced="end">Next</v-btn>

渲染时(VBtn.tsx)会根据取值追加v-btn--spacedv-btn--spaced-start/v-btn--spaced-end/v-btn--spaced-both类,由 SASS 控制图标与内容的间距。

自定义加载器

loader插槽允许你自定义加载指示器。以下示例使用 v-progress-linear 创建一个横跨按钮全宽的加载条:

<v-btn :loading="loading" @click="loading = !loading"> Custom loader <template v-slot:loader> <v-progress-linear indeterminate></v-progress-linear> </template> </v-btn>

进阶示例

以下是v-btn更高级、贴近真实世界的用例集合,全部示例位于 packages/docs/src/examples/v-btn 目录:

  • Discord eventmisc-discord-event.vue):利用多种按钮变体与样式复刻 Discord 活动卡片。
  • Survey groupmisc-group-survey.vue):除 Button groups 外,v-btn还能通过特殊 symbol 接入 v-item-group,创建一组用于选择调查答案的按钮并添加自定义active状态样式。这一机制在源码中对应 VBtn.tsx 的useGroupItem(props, props.symbol, false)group:selected事件(VBtn.tsx),默认 symbol 为VBtnToggleSymbol
  • Tax form confirmationmisc-tax-form.vue):利用 v-text-field 收集用户数据,并在提交表单时使用loadingprop。
  • Dialog actionmisc-dialog-action.vue):按钮常用于触发 v-dialog 内的操作,此例用outlined变体与colorprop 让按钮在视觉上与其他按钮区分。
  • Cookie settingsmisc-cookie-settings.vue):使用 v-banner 展示自定义 Cookie 同意横幅,点击 "Manage Cookies" 按钮弹出 v-dialog。
  • Readonly buttonsmisc-readonly.vue):根据 "订阅" 状态改变v-btn属性。用户已订阅时希望禁用按钮交互但不改变外观(这正是disabled属性会触发的效果),因此使用readonly方案——源码中v-btn--readonly类与tabindex: -1(VBtn.tsx)保证了只读状态不可聚焦、不可交互但外观不变。

全局配置(Global Configuration)

通过 Global configuration 可以修改所有v-btn组件的默认值并设置默认样式。这有助于保持应用一致性,并让你在未来以最小成本修改:

// src/plugins/vuetify.js import { createVuetify } from 'vuetify' export default createVuetify({ defaults: { VBtn: { color: 'primary', variant: 'outlined', rounded: true, }, }, })

组件别名(Aliasing)

利用 component aliasing 特性,可以从v-btn派生出虚拟组件。这在设计规范中存在大量按钮变体、或基于 Vuetify 开发自定义组件库时非常有用:

// src/plugins/vuetify.js import { createVuetify } from 'vuetify' import { VBtn } from 'vuetify/components' export default createVuetify({ aliases: { VBtnSecondary: VBtn, VBtnTertiary: VBtn, }, defaults: { VBtn: { color: 'primary', variant: 'text', }, VBtnSecondary: { color: 'secondary', variant: 'flat', }, VBtnTertiary: { rounded: true, variant: 'plain', }, }, })

这样VBtnSecondaryVBtnTertiary便成为可全局使用的独立组件名,且各自拥有独立默认值。

SASS 变量定制

通过修改v-btn的 SASS variables 可以做出精细调整,例如改变默认按钮高度或内边距:

// src/settings.scss @use 'vuetify/settings' with ( $button-border-radius: 16px, $button-height: 32px, );

_variables.scss 中可覆盖的核心变量包括:

| 变量 | 默认值 | 说明 | | - | - | - | |$button-border-radius|settings.$border-radius-root| 按钮圆角 | |$button-height|36px| 默认按钮高度 | |$button-stacked-height|72px| 堆叠按钮高度 | |$button-font-size|label-large字号 | 字体大小 | |$button-plain-opacity|.62| plain 变体未悬停时的不透明度 | |$button-disabled-opacity|0.26| 禁用态透明度 | |$button-slim-padding|0 8px| slim 模式水平内边距(8px) | |$button-density|(default: 0, comfortable: -2, compact: -3)| 密度偏移映射 | |$button-width-ratio|16 / 9| 宽度与高度比 | |$button-padding-ratio|2.25| 水平内边距与高度比 |

其中部分值也可以通过 Global configuration 修改,且优先级高于 SASS 变量。例如heightprop 可以直接改变按钮默认高度而无需修改 SASS 变量(makeDimensionProps产生的dimensionStyles会以行内样式覆盖)。

默认值副作用(Defaults Side Effects)

存在一些情况会向v-btn注入一组默认属性或应用自定义样式,常见原因包括:

  • 匹配设计规范;
  • 基于上下文提供更好的视觉效果;
  • 避免创建专有组件,例如v-bottom-navigation-btnv-card-btn

这些行为主要由VDefaultsProvider与各容器组件的内部默认值实现,源码可参见各组件目录下的实现与 packages/docs/src/examples/v-btn 中的defaults-*示例。

Banners(横幅)

v-banner-actions组件为按钮应用text变体和slimprop,将按钮 x 轴内边距缩减至8px

| 文档 | API | | - | - | | Banners | v-banner-actions |

v-banner-actions内被修改的属性:

| 属性 | 值 | | - | - | |color| 由v-banner-actions提供 | |density| 由v-banner-actions提供 | |slim|true| |variant|text|

Bottom navigation(底部导航)

v-bottom-navigation组件会隔离之前提供的所有默认值并应用自己的默认值,以避免 Global configuration 中对v-btn的修改影响底部导航。按钮会自动注册到v-bottom-navigation的组(group)中,点击时更新其model

| 文档 | API | | - | - | | Bottom navigation | v-bottom-navigation |

v-bottom-navigation内被修改的属性:

| 属性 | 值 | | - | - | |color| 由v-bottom-navigation提供 | |density| 由v-bottom-navigation提供 | |stacked| 当modeshift时为true| |variant|text|

Button groups(按钮组)

v-btn-group组件对v-btn做了多项修改。

| 文档 | API | | - | - | | Button groups | v-btn-group |

v-btn-group内被修改的属性:

| 属性 | 值 | | - | - | |color| 由v-btn-group提供 | |height|auto| |density| 由v-btn-group提供 | |flat|true| |size| 由v-btn-group提供(需要 v3.13.0 或 v4.2.0 及以上版本) | |variant| 由v-btn-group提供 |

Size 继承

当组上设置了size,子按钮会继承该尺寸,且组高度与同尺寸的独立按钮保持一致。此特性需要 v3.13.0 或 v4.2.0 及以上版本。

Cards(卡片)

v-card-actions组件为按钮应用text变体和slimprop(x 轴内边距缩减至8px),并对所有兄弟元素应用起始外边距(start margin)。这保证了按钮文本与卡片文本、标题对齐,并在操作之间保留间距。

| 文档 | API | | - | - | | Cards | v-card-actions |

v-card-actions内被修改的属性:

| 属性 | 值 | | - | - | |slim|true| |variant|text|

Snackbars(消息条)

v-snackbar组件为所有v-btn应用text变体、slimprop,并移除涟漪效果。

| 文档 | API | | - | - | | Snackbars | v-snackbar |

v-snackbaractions插槽内被修改的属性:

| 属性 | 值 | | - | - | |slim|true| |ripple|false| |variant|text|

Toolbars 与 AppBars(工具栏与应用栏)

v-toolbar组件为所有v-btn应用text变体。此外,v-toolbar-items组件用于创建填满工具栏高度的按钮分组。

| 文档 | API | | - | - | | Toolbars | v-toolbar |

::: info v-app-bar 组件内部使用 v-toolbar。应用全局默认值时,必须针对v-toolbar组件。 :::

// src/plugins/vuetify.js export default createVuetify({ defaults: { VToolbar: { VBtn: { variant: 'flat' }, }, }, })

v-toolbarv-toolbar-items内被修改的属性:

| 属性 | 值 | | - | - | |height| 由v-toolbar-items提供 | |variant|text|

无障碍(Accessibility)

v-btn组件是原生button元素的扩展,支持原生按钮的全部无障碍特性。

ARIA 属性

默认情况下,v-btn包含相关的 WAI-ARIA 属性以增强可访问性。组件自动被赋予type="button"属性,向辅助技术表明其按钮用途(见 VBtn.tsx 中type={ Tag === 'a' ? undefined : 'button' };当按钮渲染为链接<a>时不设置 type)。加载状态下还会自动设置aria-busy(VBtn.tsx)。

键盘导航

v-btn原生可聚焦,并响应键盘事件,例如按EnterSpace键触发按钮动作,保证用户仅凭键盘即可导航和操作应用。

可访问标签

当在v-btn内使用 v-icon(例如通过iconprop)时,必须为屏幕阅读器用户提供文本替代。可以添加aria-label属性并给出描述性标签,确保按钮用途对所有用户清晰:

<v-btn aria-label="Refresh" icon="mdi-refresh" ></v-btn>

触控目标尺寸

确保按钮具有足够的触控目标尺寸,尤其在触屏设备上。更大的触控目标可以改善运动障碍用户或小屏幕用户的可用性。可以使用sizeprop 的largex-large值增大按钮:

<v-btn size="large"> Large Button </v-btn> <v-btn size="x-large"> Extra Large Button </v-btn>

源码参考

想要深入理解v-btn的实现细节,可以阅读以下文件:

  • 组件实现:packages/vuetify/src/components/VBtn/VBtn.tsx——Props 定义、渲染逻辑、插槽输出与涟漪绑定。
  • 组件样式:packages/vuetify/src/components/VBtn/VBtn.sass——基础布局、密度/尺寸 mixin 调用、变体与焦点可见性样式。
  • 尺寸与密度 mixin:packages/vuetify/src/components/VBtn/_mixins.scss。
  • 默认变量:packages/vuetify/src/components/VBtn/_variables.scss——所有 SASS 可覆盖变量。
  • 浏览器端测试:packages/vuetify/src/components/VBtn/tests/VBtn.spec.browser.tsx。
  • 交互示例:packages/docs/src/examples/v-btn(含usage.vueprop-*slot-*misc-*defaults-*等 33 个示例文件)。

【免费下载链接】vuetify🐉 Vue Component Framework项目地址: https://gitcode.com/gh_mirrors/vu/vuetify

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

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

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

立即咨询