Nuxt UI v4 标志着一个重要的里程碑:Nuxt UI 和 Nuxt UI Pro 现已统一到一个单一的、完全开源的免费库中。您现在可以通过 @nuxt/ui 包访问 100 多个生产就绪组件。
本指南提供了从 v3 迁移到 v4 的分步说明。
package.json 中将 @nuxt/ui-pro 替换为 @nuxt/uipnpm remove @nuxt/ui-pro
pnpm add @nuxt/ui
yarn remove @nuxt/ui-pro
yarn add @nuxt/ui
npm uninstall @nuxt/ui-pro
npm install @nuxt/ui
bun remove @nuxt/ui-pro
bun add @nuxt/ui
nuxt.config.ts 中将 @nuxt/ui-pro 替换为 @nuxt/uiexport default defineNuxtConfig({
modules: [
- '@nuxt/ui-pro',
+ '@nuxt/ui'
]
})
vite.config.ts 中将 @nuxt/ui-pro 替换为 @nuxt/uiimport { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
- import uiPro from '@nuxt/ui-pro/vite'
+ import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
- uiPro({
+ ui({
ui: {
colors: {
primary: 'green',
neutral: 'slate'
}
}
})
]
})
app.config.ts 中使用 ui 键而不是 uiProexport default defineAppConfig({
ui: {
colors: {
primary: 'green',
neutral: 'slate'
},
+ pageCard: {
+ slots: {
+ root: 'rounded-xl',
+ }
+ }
},
- uiPro: {
- pageCard: {
- slots: {
- root: 'rounded-xl',
- }
- }
- }
})
vite.config.ts 中使用 ui 键而不是 uiProexport default defineConfig({
plugins: [
vue(),
ui({
ui: {
colors: {
primary: 'green',
neutral: 'slate'
},
+ pageCard: {
+ slots: {
+ root: 'rounded-xl',
+ }
+ }
},
- uiPro: {
- pageCard: {
- slots: {
- root: 'rounded-xl',
- }
- }
- }
})
]
})
@nuxt/ui-pro 替换为 @nuxt/ui@import "tailwindcss";
- @import "@nuxt/ui-pro";
+ @import "@nuxt/ui";
@source 指令以匹配新的目录结构。@import "tailwindcss";
@import "@nuxt/ui";
- @source "../../content/**/*";
+ @source "../../../content/**/*";
@import "tailwindcss";
- @import "@nuxt/ui-pro";
+ @import "@nuxt/ui";
@nuxt/ui-pro 替换为 @nuxt/ui- import type { BannerProps } from '@nuxt/ui-pro'
+ import type { BannerProps } from '@nuxt/ui'
pnpm add @nuxt/ui
yarn add @nuxt/ui
npm install @nuxt/ui
bun add @nuxt/ui
升级到 Nuxt UI v4 后,请注意以下重要变更
ButtonGroup 组件已重命名为 FieldGroup
<template>
- <UButtonGroup>
+ <UFieldGroup>
<UButton label="Button" />
<UButton icon="i-lucide-chevron-down" />
+ </UFieldGroup>
- </UButtonGroup>
</template>
PageMarquee 组件已重命名为 Marquee
<template>
- <UPageMarquee :items="items" />
+ <UMarquee :items="items" />
</template>
PageAccordion 组件已移除,取而代之的是 Accordion
<template>
- <UPageAccordion
+ <UAccordion
:items="items"
+ :unmount-on-hide="false"
+ :ui="{ trigger: 'text-base', body: 'text-base text-muted' }"
/>
</template>
PageAccordion 组件是一个包装器,它将 unmount-on-hide 设置为 false 并自定义了 ui 属性。Input、InputNumber 和 Textarea 使用的 modelModifiers 结构在 v4 中已更改
nullify 修饰符已重命名为 nullable(它将空/空白值转换为 null)。optional 修饰符(它将空/空白值转换为 undefined)。- <UInput v-model.nullify="value" />
+ <UInput v-model.nullable="value" />
- <UTextarea v-model="value" :model-modifiers="{ nullify: true }" />
+ <UTextarea v-model="value" :model-modifiers="{ nullable: true }" />
当您希望空值为 null 时使用 nullable,当您希望缺失值为 undefined 时使用 optional。
Form 组件在 v4 中得到了改进,具有更好的状态管理和嵌套表单处理。以下是您需要注意的关键更改
@submit 数据,并且不再改变表单的状态。这提供了更好的可预测性并防止意外的状态突变。nested 属性显式启用嵌套表单。这使得组件行为更明确,并防止意外的嵌套表单创建。name 属性(类似于 UFormField),并将自动从其父表单继承其状态。<template>
<UForm :state="state" :schema="schema" @submit="onSubmit">
<UFormField label="Customer" name="customer">
<UInput v-model="state.customer" placeholder="Wonka Industries" />
</UFormField>
<div v-for="(item, index) in state.items" :key="index">
<UForm
- :state="item"
+ :name="`items.${index}`"
:schema="itemSchema"
+ nested
>
<UFormField :label="!index ? 'Description' : undefined" name="description">
<UInput v-model="item.description" />
</UFormField>
<UFormField :label="!index ? 'Price' : undefined" name="price">
<UInput v-model="item.price" type="number" />
</UFormField>
</UForm>
</div>
</UForm>
</template>
Nuxt UI Pro 中之前可用的一些 Nuxt Content 实用工具在 v4 中已移除
findPageBreadcrumbfindPageHeadline这些现在完全由 Nuxt Content 提供。请务必相应地更新您的导入和用法。
- import { findPageHeadline } from '@nuxt/ui-pro/utils/content'
+ import { findPageHeadline } from '@nuxt/content/utils'
- import { findPageBreadcrumb } from '@nuxt/ui-pro/utils/content'
+ import { findPageBreadcrumb } from '@nuxt/content/utils'
本节仅适用于您正在使用 AI SDK 和聊天组件(ChatMessage、ChatMessages、ChatPrompt、ChatPromptSubmit、ChatPalette)。如果您未使用 AI 功能,可以跳过本节。
package.json 中更新 @ai-sdk/vue 和 ai 依赖项{
"dependencies": {
- "@ai-sdk/vue": "^1.2.x",
+ "@ai-sdk/vue": "^2.0.x",
- "ai": "^4.3.x"
+ "ai": "^5.0.x"
}
}
useChat 可组合函数已替换为新的 Chat 类<script setup lang="ts">
- import { useChat } from '@ai-sdk/vue'
+ import { Chat } from '@ai-sdk/vue'
+ import type { UIMessage } from 'ai'
- const { messages, input, handleSubmit, status, error, reload, setMessages } = useChat()
+ const messages: UIMessage[] = []
+ const input = ref('')
+
+ const chat = new Chat({
+ messages
+ })
+
+ function handleSubmit() {
+ chat.sendMessage({ text: input.value })
+ input.value = ''
+ }
</script>
parts 而不是 content// When manually creating messages
- setMessages([{
+ messages.push({
id: '1',
role: 'user',
- content: 'Hello world'
+ parts: [{ type: 'text', text: 'Hello world' }]
- }])
+ })
// In templates
<template>
- <UChatMessage :content="message.content" />
+ <UChatMessage :parts="message.parts" />
</template>
// Regenerate the last message
- reload()
+ chat.regenerate()
// Access chat state
- :messages="messages"
- :status="status"
+ :messages="chat.messages"
+ :status="chat.status"
getTextFromMessage 实用工具,用于从 AI SDK v5 消息部分中提取文本<script setup lang="ts">
import { getTextFromMessage } from '@nuxt/ui/utils/ai'
</script>
<template>
<UChatMessages :messages="chat.messages" :status="chat.status">
<template #content="{ message }">
<!-- Extract text from message parts and render with MDC -->
<MDC :value="getTextFromMessage(message)" :cache-key="message.id" class="*:first:mt-0 *:last:mb-0" />
</template>
</UChatMessages>
</template>