Vuetify 是一个基于 Vue.js 的开源 UI 库,它提供了大量精心制作的组件,遵循 Google 的 Material Design 规范。使用 Vuetify,开发者可以无需设计技能就能创建出美观、响应式的应用程序。以下是对 Vuetify 的详细介绍,包含代码示例和详细说明。
Vuetify 简介
Vuetify 旨在为开发人员提供构建丰富且引人入胜的用户体验所需的所有工具。自 Vue.js 首次发布以来,它已经成为世界上最受欢迎的 JavaScript 框架之一,部分原因是其广泛的组件使用,使得开发人员能够创建小模块,并在应用程序中进行使用和重复使用。
为什么选择 Vuetify
- 开源免费:Vuetify 是一个开源项目,根据 MIT 许可证免费提供,源代码可在 GitHub 上获取,让开发人员可以根据需要进行修改和贡献以推动其发展。
- 灵活的组件:每个 Vuetify 组件都是在 Google 的 Material Design 规范下精心制作的,并提供数百种定制选项,适用于任何风格或设计。
- 强大的工具生态系统:Vuetify 拥有庞大的支持工具生态系统,包括 Figma UI 组件套件、Vite 支持、预配置的 Vue 3 应用程序、对 VSCode 和 JetBrains 的产品的智能感知和自动完成支持等。
快速入门
要开始使用 Vuetify 3,可以使用以下命令创建新项目:
# 使用 yarn
yarn create vuetify
# 使用 npm
npm create vuetify@latest
# 使用 pnpm
pnpm create vuetify
# 使用 bun
bun create vuetify
创建项目后,你将被提示选择预设和安装依赖项的方式。选择完毕后,使用 cd 切换到项目目录,然后使用 pnpm run dev(或相应的命令)运行项目。
项目结构
Vuetify 项目通常具有以下结构:
my-vuetify-app
│ README.md
│ package.json
│
├─public/
│ index.html
│
└─src/
│ main.js
│
├─components/
├─views/
└─vuetify/
public/index.html:入口 HTML 文件。src/main.js:入口 JavaScript 文件,用于创建 Vue 应用实例。src/components和src/views:存放 Vue 组件和视图。src/vuetify/:Vuetify 配置目录,可以配置主题、插件等。
代码示例
以下是一个使用 Vuetify 的简单数据表格组件示例:
<template>
<v-data-table
:headers="headers"
:items="desserts"
:items-per-page="5"
class="elevation-1"
>
</v-data-table>
</template>
<script>
export default {
data() {
return {
headers: [
{ text: 'Dessert (100g serving)', align: 'start', sortable: false, value: 'name' },
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
// 这里是数据数组
],
};
},
};
</script>
组件和 API
Vuetify 提供了超过 80 个语义化的 Vue 组件,每个组件都有详细的 API 文档,可以轻松地进行定制和扩展。
社区和支持
Vuetify 拥有一个庞大的社区,提供在 Discord 上的支持,当你遇到障碍时,可以快速获得帮助。
主题系统与自定义主题
Vuetify 3 的主题系统基于 CSS 变量,支持动态切换和深度定制:
// src/vuetify/theme.js
import { createVuetify } from 'vuetify'
export default createVuetify({
theme: {
defaultTheme: 'light',
themes: {
light: {
dark: false,
colors: {
primary: '#1976D2',
secondary: '#424242',
accent: '#82B1FF',
error: '#FF5252',
info: '#2196F3',
success: '#4CAF50',
warning: '#FFC107',
background: '#FAFAFA',
surface: '#FFFFFF',
},
},
dark: {
dark: true,
colors: {
primary: '#90CAF9',
background: '#121212',
surface: '#1E1E1E',
},
},
custom: {
dark: false,
colors: {
primary: '#6D28D9',
secondary: '#EC4899',
accent: '#F59E0B',
},
},
},
},
})
<!-- 动态切换主题 -->
<template>
<v-app>
<v-btn @click="toggleTheme" icon>
<v-icon>{{ isDark ? 'mdi-weather-sunny' : 'mdi-weather-night' }}</v-icon>
</v-btn>
</v-app>
</template>
<script setup>
import { ref, computed } from 'vue'
import { useTheme } from 'vuetify'
const theme = useTheme()
const isDark = computed(() => theme.global.current.value.dark)
function toggleTheme() {
theme.global.name.value = isDark.value ? 'light' : 'dark'
}
</script>
响应式布局与断点系统
Vuetify 的栅格系统基于 Flexbox,提供 5 个断点:
| 断点名 | 范围 | 典型设备 |
|---|---|---|
xs | < 600px | 手机 |
sm | 600px - 960px | 平板竖屏 |
md | 960px - 1280px | 平板横屏 / 小笔记本 |
lg | 1280px - 1920px | 桌面显示器 |
xl | > 1920px | 大屏幕 |
<template>
<v-container>
<v-row>
<!-- 手机独占一行,平板占一半,桌面占三分之一 -->
<v-col cols="12" sm="6" md="4" lg="3">
<v-card>卡片 1</v-card>
</v-col>
<v-col cols="12" sm="6" md="4" lg="3">
<v-card>卡片 2</v-card>
</v-col>
<v-col cols="12" sm="6" md="4" lg="3">
<v-card>卡片 3</v-card>
</v-col>
</v-row>
<!-- 使用 display 工具类控制可见性 -->
<v-btn class="d-none d-md-flex">仅桌面端显示的按钮</v-btn>
<v-btn class="d-md-none">仅移动端显示的按钮</v-btn>
</v-container>
</template>
组合式 API 中的响应式工具
<script setup>
import { useDisplay } from 'vuetify'
const { mobile, mdAndUp, width, name } = useDisplay()
// mobile: 是否为移动端
// mdAndUp: 是否 >= md 断点
// width: 当前视口宽度
// name: 当前断点名 (xs/sm/md/lg/xl)
</script>
表单验证与 VeeValidate 集成
<template>
<v-form @submit.prevent="submit" ref="formRef">
<v-text-field
v-model="email"
label="邮箱"
:rules="[rules.required, rules.email]"
prepend-icon="mdi-email"
/>
<v-text-field
v-model="password"
label="密码"
type="password"
:rules="[rules.required, rules.minLength]"
prepend-icon="mdi-lock"
/>
<v-btn type="submit" color="primary" :loading="loading">
提交
</v-btn>
</v-form>
</template>
<script setup>
import { ref } from 'vue'
const formRef = ref(null)
const email = ref('')
const password = ref('')
const loading = ref(false)
const rules = {
required: v => !!v || '此项为必填',
email: v => /.+@.+\..+/.test(v) || '请输入有效的邮箱地址',
minLength: v => v.length >= 8 || '密码至少8位',
}
async function submit() {
const { valid } = await formRef.value.validate()
if (!valid) return
loading.value = true
try {
await login({ email: email.value, password: password.value })
} finally {
loading.value = false
}
}
</script>
性能优化
Tree-shaking 按需加载
Vuetify 3 支持自动 tree-shaking,只打包使用到的组件:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vuetify from 'vite-plugin-vuetify'
export default defineConfig({
plugins: [
vue(),
vuetify({
autoImport: true, // 自动按需导入组件
styles: { configFile: 'src/vuetify/settings.scss' }
}),
],
build: {
chunkSizeWarningLimit: 500,
rollupOptions: {
output: {
manualChunks: {
vuetify: ['vuetify'],
},
},
},
},
})
图标按需加载
// 只导入使用到的图标,而非全部 MDI
import { mdiAccount, mdiEmail, mdiLock } from '@mdi/js'
const aliases = {
account: mdiAccount,
email: mdiEmail,
lock: mdiLock,
}
虚拟滚动处理大数据
<template>
<!-- 10万行数据不卡顿 -->
<v-virtual-scroll
:items="items"
height="400"
item-height="50"
>
<template v-slot:default="{ item }">
<v-list-item :title="item.name" :subtitle="item.email" />
</template>
</v-virtual-scroll>
</template>
国际化 (i18n)
// src/vuetify/i18n.js
import { createVuetify } from 'vuetify'
import { zhHans, en } from 'vuetify/locale'
export default createVuetify({
locale: {
locale: 'zhHans',
fallback: 'en',
messages: { zhHans, en },
},
})
<template>
<!-- 日期和数字自动本地化 -->
<v-date-picker v-model="date" />
<v-number-input v-model="amount" :min="0" />
</template>
结论
Vuetify 是一个功能强大的 Vue 组件框架,提供了丰富的组件和工具,使得构建现代化的 Web 应用变得简单快捷。通过本教程,你应该对 Vuetify 有了全面的了解,包括主题定制、响应式布局、表单验证、性能优化与国际化。对于企业级应用,建议结合 Pinia 状态管理与 Vue Router 构建完整的单页应用架构。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。