迁移

将您的应用程序从 Nuxt UI v2 迁移到 Nuxt UI v3 的综合指南。

Nuxt UI v3.0 是一个从零开始重构的全新主要版本,引入了现代架构,显著提升了性能并增强了开发者体验。此主要版本包含了一些破坏性变更,同时带来了强大的新特性和功能

  • Tailwind CSS v4:从基于 JavaScript 的配置迁移到基于 CSS 的配置
  • Reka UI:取代 Headless UI 成为底层组件库
  • Tailwind Variants:用于组件变体的新样式 API

本指南提供了将您的应用程序从 v2 迁移到 v3 的分步说明。

迁移您的项目

更新 Tailwind CSS

Tailwind CSS v4 对其配置方法进行了重大更改。官方的 Tailwind 升级工具将有助于自动化大部分迁移过程。

有关所有更改的详细说明,请参阅官方的 Tailwind CSS v4 升级指南
  1. 创建一个 main.css 文件,并将其导入到您的 nuxt.config.ts 文件中
@import "tailwindcss";
  1. 运行 Tailwind CSS 升级工具
npx @tailwindcss/upgrade

更新 Nuxt UI

  1. 安装最新版本的包
pnpm add @nuxt/ui
pnpm add @nuxt/ui-pro
  1. 将其导入到您的 CSS 中
app/assets/css/main.css
@import "tailwindcss";
@import "@nuxt/ui";
app/assets/css/main.css
@import "tailwindcss";
@import "@nuxt/ui-pro";
  1. 使用 App 组件包裹您的应用程序
  1. 在您的 nuxt.config.ts 文件中添加 @nuxt/ui-pro 模块,因为它不再是一个层级
nuxt.config.ts
export default defineNuxtConfig({
-  extends: ['@nuxt/ui-pro'],
-  modules: ['@nuxt/ui']
+  modules: ['@nuxt/ui-pro']
})
  1. 使用 App 组件包裹您的应用程序
app.vue
<template>
  <UApp>
    <NuxtPage />
  </UApp>
</template>

v2 的变更

现在您已经更新了项目,可以开始迁移代码了。以下是 Nuxt UI v3 中所有破坏性变更的综合列表。

更新的设计系统

在 Nuxt UI v2 中,我们有一个设计系统,它混合了 primarygrayerror 别名以及所有 Tailwind CSS 的颜色。我们已将其替换为包含 7 种颜色别名的完整设计系统

颜色默认值描述
primary绿色主要品牌色,用作组件的默认颜色。
secondary蓝色补充主色的次要颜色。
success绿色用于成功状态。
info蓝色用于信息状态。
warning黄色用于警告状态。
error红色用于表单错误验证状态。
neutral石板灰用于背景、文本等的中性颜色。

此更改引入了您需要注意的几个破坏性变更

  • 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 属性中的 grayblackwhite 已被移除,取而代之的是 neutral
- <UButton color="black" />
+ <UButton color="neutral" />

- <UButton color="gray" />
+ <UButton color="neutral" variant="subtle" />

- <UButton color="white" />
+ <UButton color="neutral" variant="outline" />
  • 您不能再在 color 属性中使用 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.tsui 属性进行的所有覆盖都已过时。

export default defineAppConfig({
   ui: {
     button: {
-       font: 'font-bold',
-       default: {
-         size: 'md',
-         color: 'primary'
-       }
+       slots: {
+         base: 'font-medium'
+       },
+       defaultVariants: {
+         size: 'md',
+         color: 'primary'
+       }
     }
   }
})
  • 更新您的ui 属性,以使用其新主题覆盖每个组件的插槽
<template>
- <UButton :ui="{ font: 'font-bold' }" />
+ <UButton :ui="{ base: 'font-bold' }" />
</template>
我们无法在此处详细说明所有更改,但您可以在主题部分查看每个组件的主题。

重命名组件

我们已重命名一些 Nuxt UI 组件,以与 Reka UI 命名约定保持一致

v2v3
DividerSeparator
DropdownDropdownMenu
FormGroupFormField
RangeSlider
ToggleSwitch
NotificationToast
VerticalNavigationNavigationMenu 使用 orientation="vertical"
HorizontalNavigationNavigationMenu 使用 orientation="horizontal"

以下是已重命名或移除的 Nuxt UI 专业版组件

v1v3
BlogListBlogPosts
ColorModeToggleColorModeSwitch
DashboardCard已移除(请改用 PageCard
DashboardLayoutDashboardGroup
DashboardModal已移除(请改用 Modal
DashboardNavbarToggleDashboardSidebarToggle
DashboardPage已移除
DashboardPanelContent已移除(请改用 #body 插槽)
DashboardPanelHandleDashboardResizeHandle
DashboardSection已移除(请改用 PageCard
DashboardSidebarLinks已移除(请改用 NavigationMenu
DashboardSlideover已移除(请改用 Slideover
FooterLinks已移除(请改用 NavigationMenu
HeaderLinks已移除(请改用 NavigationMenu
LandingCard已移除(请改用 PageCard
LandingCTAPageCTA
LandingFAQ已移除(请改用 PageAccordion
LandingGrid已移除(请改用 PageGrid
LandingHero已移除(请改用 PageHero
LandingLogosPageLogos
LandingSectionPageSection
LandingTestimonial已移除(请改用 PageCard
NavigationAccordionContentNavigation
NavigationLinksContentNavigation
NavigationTreeContentNavigation
PageError错误
PricingCardPricingPlan
PricingGridPricingPlans
PricingSwitch已移除(请改用 SwitchTabs

变更的组件

除了重命名的组件之外,组件 API 还有许多更改。下面我们详细介绍最重要的几项

  • 为了保持一致性,linksoptions 属性已重命名为 items
<template>
- <USelect :options="countries" />
+ <USelect :items="countries" />

- <UHorizontalNavigation :links="links" />
+ <UNavigationMenu :items="links" />
</template>
此更改影响以下组件:BreadcrumbHorizontalNavigationInputMenuRadioGroupSelectSelectMenuVerticalNavigation
  • 不同组件中的 click 字段已被移除,取而代之的是原生的 Vue onClick 事件
<script setup lang="ts">
const items = [{
  label: 'Edit',
-  click: () => {
+  onClick: () => {
    console.log('Edit')
  }
}]
</script>
此更改影响 Toast 组件以及所有具有 items 链接的组件,例如 NavigationMenuDropdownMenuCommandPalette 等。
  • 全局的 ModalsSlideoversNotifications 组件已被移除,取而代之的是 App 组件
app.vue
<template>
+  <UApp>
+    <NuxtPage />
+  </UApp>
-  <UModals />
-  <USlideovers />
-  <UNotifications />
</template>
  • v-model:open 指令 和 default-open 属性现在用于控制可见性
<template>
- <UModal v-model="open" />
+ <UModal v-model:open="open" />
</template>
此更改影响以下组件:ContextMenuModalSlideover,并可用于控制 InputMenuSelectSelectMenuTooltip 的可见性。
  • 默认插槽现在用于触发器,内容位于 #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>
此更改影响以下组件:ModalPopoverSlideoverTooltip
  • #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>
此更改影响以下组件:ModalSlideover

变更的可组合项

  • useToast() 可组合项的 timeout 属性已重命名为 duration
<script setup lang="ts">
const toast = useToast()

- toast.add({ title: 'Invitation sent', timeout: 0 })
+ toast.add({ title: 'Invitation sent', duration: 0 })
</script>
  • useModaluseSlideover 可组合项已被移除,取而代之的是更通用的 useOverlay 可组合项

一些重要区别

  • useOverlay 可组合项现在用于创建覆盖实例
  • 已打开的覆盖层可以等待其结果
  • 覆盖层不能再使用 modal.close()slideover.close() 关闭,而是会自动关闭:当从已打开的组件明确触发 close 事件时,或者当覆盖层自身关闭时(点击背景、按下 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 属性传递

<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>

变更的表单验证

  • 用于定位表单字段的错误对象属性已从 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>

此页面正在完善中,我们会定期进行改进。