迁移到 v3
一份全面的指南,帮助您将应用程序从 Nuxt UI v2 迁移到 Nuxt UI v3。
Nuxt UI v3 是一个全新的主版本,从头开始重建,引入了现代化的架构,显著提升了性能并增强了开发体验。此主要版本包含多项重大更改,同时也引入了强大的新功能和能力。
- Tailwind CSS v4:从 JavaScript 到 CSS 配置的迁移
- Reka UI:用 Headless UI 替换作为底层组件库
- Tailwind Variants:用于组件变体的全新样式 API
本指南提供了从 v2 迁移到 v3 的分步说明。
迁移您的项目
更新 Tailwind CSS
Tailwind CSS v4 引入了其配置方法上的重大变化。官方的 Tailwind 升级工具将帮助自动化大部分迁移过程。
- 创建一个
main.css
文件并在您的nuxt.config.ts
文件中导入它
@import "tailwindcss";
export default defineNuxtConfig({
css: ['~/assets/css/main.css']
})
- 运行 Tailwind CSS 升级工具
npx @tailwindcss/upgrade
更新 Nuxt UI
- 安装最新版本的软件包
pnpm add @nuxt/ui
yarn add @nuxt/ui
npm install @nuxt/ui
bun add @nuxt/ui
- 在您的 CSS 中导入它
app/assets/css/main.css
@import "tailwindcss";
@import "@nuxt/ui";
- 使用 App 组件包装您的应用
app.vue
<template>
<UApp>
<NuxtPage />
</UApp>
</template>
v2 的更改
现在您已经更新了项目,可以开始迁移您的代码了。这是 Nuxt UI v3 中所有重大更改的完整列表。
更新的设计系统
在 Nuxt UI v2 中,我们混合使用了具有 primary
、gray
、error
别名和所有 Tailwind CSS 颜色的设计系统。我们用一个更完善的 设计系统 取代了它,该系统包含 7 种颜色别名
颜色 | 默认值 | 描述 |
---|---|---|
primary | green | 主要品牌颜色,用作组件的默认颜色。 |
secondary | blue | 次要颜色,以补充主要颜色。 |
success | green | 用于成功状态。 |
info | blue | 用于信息状态。 |
warning | yellow | 用于警告状态。 |
error | red | 用于表单错误验证状态。 |
neutral | slate | 用于背景、文本等的中间色。 |
此更改引入了几项重大更改,您需要注意
gray
颜色已重命名为neutral
<template>
- <p class="text-gray-500 dark:text-gray-400" />
+ <p class="text-neutral-500 dark:text-neutral-400" />
</template>
您还可以使用新的 设计令牌 来处理浅色和深色模式
<template>
- <p class="text-gray-500 dark:text-gray-400" />
+ <p class="text-muted" />
- <p class="text-gray-900 dark:text-white" />
+ <p class="text-highlighted" />
</template>
color
prop 中的gray
、black
和white
已被移除,改为使用neutral
- <UButton color="black" />
+ <UButton color="neutral" />
- <UButton color="gray" />
+ <UButton color="neutral" variant="subtle" />
- <UButton color="white" />
+ <UButton color="neutral" variant="outline" />
- 您不能再在
color
prop 中使用 Tailwind CSS 颜色,请使用新的别名
- <UButton color="red" />
+ <UButton color="error" />
app.config.ts
中的颜色配置已移至colors
对象
export default defineAppConfig({
ui: {
- primary: 'green',
- gray: 'cool'
+ colors: {
+ primary: 'green',
+ neutral: 'slate'
+ }
}
})
更新的主题系统
Nuxt UI 组件现在使用 Tailwind Variants API 进行样式设置,这使得您使用 app.config.ts
和 ui
prop 进行的所有覆盖都过时了。
- 更新您的
app.config.ts
以用新的主题覆盖组件
export default defineAppConfig({
ui: {
button: {
- font: 'font-bold',
- default: {
- size: 'md',
- color: 'primary'
- }
+ slots: {
+ base: 'font-medium'
+ },
+ defaultVariants: {
+ size: 'md',
+ color: 'primary'
+ }
}
}
})
- 更新您的
ui
prop 以用新的主题覆盖每个组件的插槽
<template>
- <UButton :ui="{ font: 'font-bold' }" />
+ <UButton :ui="{ base: 'font-bold' }" />
</template>
重命名的组件
我们重命名了一些 Nuxt UI 组件,以符合 Reka UI 的命名约定
v2 | v3 |
---|---|
Divider | Separator |
Dropdown | DropdownMenu |
FormGroup | FormField |
Range | Slider |
Toggle | Switch |
Notification | Toast |
VerticalNavigation | NavigationMenu 带有 orientation="vertical" |
HorizontalNavigation | NavigationMenu 带有 orientation="horizontal" |
以下是已重命名或移除的 Nuxt UI Pro 组件
v1 | v3 |
---|---|
BlogList | 博客文章列表 |
ColorModeToggle | 颜色模式开关 |
DashboardCard | 已移除(请改用 PageCard ) |
DashboardLayout | 仪表盘组 |
DashboardModal | 已移除(请改用 Modal ) |
DashboardNavbarToggle | 仪表盘侧边栏切换 |
DashboardPage | 已移除 |
DashboardPanelContent | 已移除(请改用 #body 插槽) |
DashboardPanelHandle | 仪表盘调整大小手柄 |
DashboardSection | 已移除(请改用 PageCard ) |
DashboardSidebarLinks | 已移除(请改用 NavigationMenu ) |
DashboardSlideover | 已移除(请改用 Slideover ) |
FooterLinks | 已移除(请改用 NavigationMenu ) |
HeaderLinks | 已移除(请改用 NavigationMenu ) |
LandingCard | 已移除(请改用 PageCard ) |
LandingCTA | 页面 CTA |
LandingFAQ | 已移除(请改用 Accordion ) |
LandingGrid | 已移除(请改用 PageGrid ) |
LandingHero | 已移除(请改用 PageHero ) |
LandingLogos | 页面标志 |
LandingSection | 页面节 |
LandingTestimonial | 已移除(请改用 PageCard ) |
NavigationAccordion | 内容导航 |
NavigationLinks | 内容导航 |
NavigationTree | 内容导航 |
PageError | 错误 |
PricingCard | 定价方案 |
PricingGrid | 定价方案列表 |
PricingSwitch | 已移除(请改用 Switch 或 Tabs ) |
已更改的组件
除了重命名的组件之外,组件 API 还有很多更改。我们来详细说明其中最重要的几个
- 为了保持一致性,
links
和options
prop 已重命名为items
<template>
- <USelect :options="countries" />
+ <USelect :items="countries" />
- <UHorizontalNavigation :links="links" />
+ <UNavigationMenu :items="links" />
</template>
此更改会影响以下组件:
Breadcrumb
、HorizontalNavigation
、InputMenu
、RadioGroup
、Select
、SelectMenu
、VerticalNavigation
。- 不同组件中的
click
字段已被移除,改为使用原生的 VueonClick
事件
<script setup lang="ts">
const items = [{
label: 'Edit',
- click: () => {
+ onClick: () => {
console.log('Edit')
}
}]
</script>
此更改会影响
Toast
组件以及所有具有 items
链接的组件,例如 NavigationMenu
、DropdownMenu
、CommandPalette
等。- 全局的
Modals
、Slideovers
和Notifications
组件已移除,改为使用 App 组件
app.vue
<template>
+ <UApp>
+ <NuxtPage />
+ </UApp>
- <UModals />
- <USlideovers />
- <UNotifications />
</template>
v-model:open
指令现在和default-open
prop 一起用于控制可见性
<template>
- <UModal v-model="open" />
+ <UModal v-model:open="open" />
</template>
此更改会影响以下组件:
ContextMenu
、Modal
和 Slideover
,并允许控制 InputMenu
、Select
、SelectMenu
和 Tooltip
的可见性。- 默认插槽现在用于触发器,内容则放在
#content
插槽中(使用此方法时您无需使用v-model:open
指令)
<script setup lang="ts">
- const open = ref(false)
</script>
<template>
- <UButton label="Open" @click="open = true" />
- <UModal v-model="open">
+ <UModal>
+ <UButton label="Open" />
+ <template #content>
<div class="p-4">
<Placeholder class="h-48" />
</div>
+ </template>
</UModal>
</template>
此更改会影响以下组件:
Modal
、Popover
、Slideover
、Tooltip
。- 在
#content
插槽内添加了#header
、#body
和#footer
插槽,类似于Card
组件
<template>
- <UModal>
+ <UModal title="Title" description="Description">
- <div class="p-4">
+ <template #body>
<Placeholder class="h-48" />
+ </template>
- </div>
</UModal>
</template>
此更改会影响以下组件:
Modal
、Slideover
。更改的组合式函数
useToast()
组合式函数的timeout
prop 已重命名为duration
<script setup lang="ts">
const toast = useToast()
- toast.add({ title: 'Invitation sent', timeout: 0 })
+ toast.add({ title: 'Invitation sent', duration: 0 })
</script>
useModal
和useSlideover
组合式函数已移除,改为使用更通用的useOverlay
组合式函数
一些重要的区别
useOverlay
组合式函数现在用于创建 overlay 实例- 打开的 overlay 可以等待其结果
- Overlay 不能再通过
modal.close()
或slideover.close()
关闭,而是自动关闭:要么当从打开的组件显式触发close
事件,要么当 overlay 自身关闭时(点击背景、按 ESC 键等) - 要在父组件中捕获返回值,您必须显式发出一个带有期望值的
close
事件
<script setup lang="ts">
import { ModalExampleComponent } from '#components'
- const modal = useModal()
+ const overlay = useOverlay()
- modal.open(ModalExampleComponent)
+ const modal = overlay.create(ModalExampleComponent)
</script>
Props 现在通过 props 属性传递
<script setup lang="ts">
import { ModalExampleComponent } from '#components'
- const modal = useModal()
+ const overlay = useOverlay()
const count = ref(0)
- modal.open(ModalExampleComponent, {
- count: count.value
- })
+ const modal = overlay.create(ModalExampleComponent, {
+ props: {
+ count: count.value
+ }
+ })
</script>
关闭模态框现在通过 close
事件完成。 modal.open
方法现在返回一个实例,该实例可用于等待模态框关闭时的结果
<script setup lang="ts">
import { ModalExampleComponent } from '#components'
- const modal = useModal()
+ const overlay = useOverlay()
+ const modal = overlay.create(ModalExampleComponent)
- function openModal() {
- modal.open(ModalExampleComponent, {
- onSuccess() {
- toast.add({ title: 'Success!' })
- }
- })
- }
+ async function openModal() {
+ const instance = modal.open(ModalExampleComponent, {
+ count: count.value
+ })
+
+ const result = await instance.result
+
+ if (result) {
+ toast.add({ title: 'Success!' })
+ }
+ }
</script>
更改的表单验证
- 用于定位表单字段的 error 对象属性已从
path
重命名为name
<script setup lang="ts">
const validate = (state: any): FormError[] => {
const errors = []
if (!state.email) {
errors.push({
- path: 'email',
+ name: 'email',
message: 'Required'
})
}
if (!state.password) {
errors.push({
- path: 'password',
+ name: 'password',
message: 'Required'
})
}
return errors
}
</script>
此页面正在开发中,我们将定期进行改进。