迁移

从 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 模块,因为它不再是一个层(layer)
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 个颜色别名的正式设计系统

颜色默认描述
primarygreen主要品牌色,用作组件的默认颜色。
secondaryblue辅助颜色,用于补充主色。
successgreen用于表示成功状态。
infoblue用于表示信息状态。
warningyellow用于表示警告状态。
errorred用于表示表单验证错误状态。
neutralslate中性颜色,用于背景、文本等。

此更改引入了一些你需要注意的重大更改

  • 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
VerticalNavigationNavigationMenuorientation="vertical"
HorizontalNavigationNavigationMenuorientation="horizontal"

以下是已重命名或移除的 Nuxt UI Pro 组件

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
PageErrorError
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 方法现在返回一个 Promise,当模态框关闭时,该 Promise 会解析为模态框的结果

<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 result = await modal.open(ModalExampleComponent, {
+     count: count.value
+   })
+
+   if (result) {
+     toast.add({ title: 'Success!' })
+   }
+ }
</script>

此页面正在建设中,我们将定期改进。