components
Nuxt 會自動匯入此目錄中的任何元件(以及您可能正在使用的任何模組所註冊的元件)。
-| components/
---| AppHeader.vue
---| AppFooter.vue
<template>
<div>
<AppHeader />
<NuxtPage />
<AppFooter />
</div>
</template>
元件名稱
如果您在巢狀目錄中有一個元件,例如
-| components/
---| base/
-----| foo/
-------| Button.vue
... 那麼元件的名稱將基於其自身的路徑目錄和檔案名稱,並刪除重複的區段。因此,元件的名稱將是
<BaseFooButton />
Button.vue
重新命名為 BaseFooButton.vue
。如果您希望僅根據名稱而非路徑自動匯入元件,則需要使用組態物件的擴充形式將 pathPrefix
選項設定為 false
export default defineNuxtConfig({
components: [
{
path: '~/components',
pathPrefix: false, },
],
});
這會使用與 Nuxt 2 中相同的策略註冊元件。例如,~/components/Some/MyComponent.vue
將可用作 <MyComponent>
而不是 <SomeMyComponent>
。
動態元件
如果您想使用 Vue <component :is="someComputedComponent">
語法,您需要使用 Vue 提供的 resolveComponent
輔助程式,或直接從 #components
匯入元件並將其傳遞到 is
屬性中。
例如
<script setup lang="ts">
import { SomeComponent } from '#components'
const MyButton = resolveComponent('MyButton')
</script>
<template>
<component :is="clickable ? MyButton : 'div'" />
<component :is="SomeComponent" />
</template>
resolveComponent
來處理動態元件,請確保只插入元件的名稱,該名稱必須是字串而不是變數。或者,雖然不建議,您可以全域註冊所有元件,這會為所有元件建立非同步區塊,並使它們在整個應用程式中可用。
export default defineNuxtConfig({
components: {
+ global: true,
+ dirs: ['~/components']
},
})
您也可以透過將它們放在 ~/components/global
目錄中,或在檔案名稱中使用 .global.vue
後綴,有選擇性地全域註冊某些元件。如上所述,每個全域元件都會在單獨的區塊中呈現,因此請小心不要過度使用此功能。
global
選項也可以針對每個元件目錄進行設定。動態匯入
要動態匯入元件(也稱為延遲載入元件),您只需在元件的名稱中新增 Lazy
前綴即可。如果元件不是一直都需要,這特別有用。
透過使用 Lazy
前綴,您可以延遲載入元件程式碼直到正確的時間,這對於最佳化 JavaScript 套件大小可能很有幫助。
<script setup lang="ts">
const show = ref(false)
</script>
<template>
<div>
<h1>Mountains</h1>
<LazyMountainsList v-if="show" />
<button v-if="!show" @click="show = true">Show List</button>
</div>
</template>
直接匯入
如果您想或需要繞過 Nuxt 的自動匯入功能,您也可以明確地從 #components
匯入元件。
<script setup lang="ts">
import { NuxtLink, LazyMountainsList } from '#components'
const show = ref(false)
</script>
<template>
<div>
<h1>Mountains</h1>
<LazyMountainsList v-if="show" />
<button v-if="!show" @click="show = true">Show List</button>
<NuxtLink to="/">Home</NuxtLink>
</div>
</template>
自訂目錄
預設情況下,只會掃描 ~/components
目錄。如果您想新增其他目錄,或變更如何在該目錄的子資料夾中掃描元件,您可以將其他目錄新增至設定中
export default defineNuxtConfig({
components: [
// ~/calendar-module/components/event/Update.vue => <EventUpdate />
{ path: '~/calendar-module/components' },
// ~/user-module/components/account/UserDeleteDialog.vue => <UserDeleteDialog />
{ path: '~/user-module/components', pathPrefix: false },
// ~/components/special-components/Btn.vue => <SpecialBtn />
{ path: '~/components/special-components', prefix: 'Special' },
// It's important that this comes last if you have overrides you wish to apply
// to sub-directories of `~/components`.
//
// ~/components/Btn.vue => <Btn />
// ~/components/base/Btn.vue => <BaseBtn />
'~/components'
]
})
npm 套件
如果您想從 npm 套件自動匯入元件,您可以使用 addComponent
在 本機模組中註冊它們。
import { addComponent, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup() {
// import { MyComponent as MyAutoImportedComponent } from 'my-npm-package'
addComponent({
name: 'MyAutoImportedComponent',
export: 'MyComponent',
filePath: 'my-npm-package',
})
},
})
元件副檔名
預設情況下,在 nuxt.config.ts 的 extensions 鍵中指定的任何具有副檔名的檔案都會被視為元件。如果您需要限制應註冊為元件的檔案副檔名,您可以使用元件目錄宣告及其 extensions
鍵的擴充形式
export default defineNuxtConfig({
components: [
{
path: '~/components',
extensions: ['.vue'], }
]
})
用戶端元件
如果元件僅要在用戶端呈現,您可以將 .client
後綴新增至您的元件。
| components/
--| Comments.client.vue
<template>
<div>
<!-- this component will only be rendered on client side -->
<Comments />
</div>
</template>
#components
導入。從它們的實際路徑顯式導入這些元件不會將它們轉換為僅限客戶端的元件。.client
元件僅在掛載後才會渲染。若要使用 onMounted()
存取渲染後的模板,請在 onMounted()
Hook 的回呼中加入 await nextTick()
。伺服器元件
伺服器元件允許在客戶端應用程式中伺服器渲染個別元件。即使您正在產生靜態網站,也可以在 Nuxt 中使用伺服器元件。這使得構建混合動態元件、伺服器渲染 HTML 甚至靜態標記區塊的複雜網站成為可能。
伺服器元件可以單獨使用,也可以與客戶端元件配對使用。
獨立伺服器元件
獨立伺服器元件將始終在伺服器上渲染,也稱為 Islands 元件。
當它們的 props 更新時,這將導致一個網路請求,該請求會就地更新渲染的 HTML。
伺服器元件目前為實驗性功能,若要使用它們,您需要在 nuxt.config 中啟用 'component islands' 功能
export default defineNuxtConfig({
experimental: {
componentIslands: true
}
})
現在您可以使用 .server
後綴註冊僅限伺服器的元件,並在您的應用程式中的任何位置自動使用它們。
-| components/
---| HighlightedMarkdown.server.vue
<template>
<div>
<!--
this will automatically be rendered on the server, meaning your markdown parsing + highlighting
libraries are not included in your client bundle.
-->
<HighlightedMarkdown markdown="# Headline" />
</div>
</template>
僅限伺服器的元件在底層使用 <NuxtIsland>
,這表示 lazy
prop 和 #fallback
slot 都會傳遞給它。
伺服器元件內的客戶端元件
experimental.componentIslands.selectiveClient
設定為 true。您可以在想要在客戶端載入的元件上設定 nuxt-client
屬性,來部分注水(hydrate)元件。
<template>
<div>
<HighlightedMarkdown markdown="# Headline" />
<!-- Counter will be loaded and hydrated client-side -->
<Counter nuxt-client :count="5" />
</div>
</template>
experimental.componentIsland.selectiveClient
設定為 'deep'
時才有效,並且由於它們是在伺服器端渲染的,因此一旦在客戶端就無法互動。伺服器元件 Context
當渲染僅限伺服器的或 Islands 元件時,<NuxtIsland>
會發出一個 fetch 請求,該請求會返回一個 NuxtIslandResponse
。(如果是在伺服器上渲染,這是一個內部請求,如果是在客戶端導覽上渲染,則您可以在網路選項卡中看到該請求。)
這意味著
- 將在伺服器端建立一個新的 Vue 應用程式,以建立
NuxtIslandResponse
。 - 在渲染元件時,將建立一個新的「Island Context」。
- 您無法從應用程式的其餘部分存取「Island Context」,並且您無法從 Island 元件存取應用程式其餘部分的 Context。換句話說,伺服器元件或 Island 與應用程式的其餘部分隔離。
- 您的外掛程式將在渲染 Island 時再次執行,除非它們設定了
env: { islands: false }
(您可以在物件語法外掛程式中執行此操作)。
在 Island 元件中,您可以透過 nuxtApp.ssrContext.islandContext
存取其 Island Context。請注意,雖然 Island 元件仍標記為實驗性,但此 Context 的格式可能會變更。
display: contents;
的 <div>
中與客戶端元件配對
在這種情況下,.server
+ .client
元件是元件的兩個「一半」,可以用於伺服器端和客戶端上元件的單獨實作的高級使用案例。
-| components/
---| Comments.client.vue
---| Comments.server.vue
<template>
<div>
<!-- this component will render Comments.server on the server then Comments.client once mounted in the browser -->
<Comments />
</div>
</template>
內建的 Nuxt 元件
Nuxt 提供了許多元件,包括 <ClientOnly>
和 <DevOnly>
。您可以在 API 文件中閱讀更多相關資訊。
函式庫作者
使用自動 tree-shaking 和元件註冊來建立 Vue 元件函式庫非常容易。✨
您可以使用 components:dirs
Hook 來擴展目錄列表,而無需在您的 Nuxt 模組中進行使用者設定。
想像一下這樣的目錄結構
-| node_modules/
---| awesome-ui/
-----| components/
-------| Alert.vue
-------| Button.vue
-----| nuxt.js
-| pages/
---| index.vue
-| nuxt.config.js
然後在 awesome-ui/nuxt.js
中,您可以使用 components:dirs
Hook
import { defineNuxtModule, createResolver } from '@nuxt/kit'
export default defineNuxtModule({
hooks: {
'components:dirs': (dirs) => {
const { resolve } = createResolver(import.meta.url)
// Add ./components dir to the list
dirs.push({
path: resolve('./components'),
prefix: 'awesome'
})
}
}
})
就是這樣!現在在您的專案中,您可以在 nuxt.config
檔案中將您的 UI 函式庫作為 Nuxt 模組匯入
export default defineNuxtConfig({
modules: ['awesome-ui/nuxt']
})
... 並在我們的 pages/index.vue
中直接使用模組元件(前綴為 awesome-
)
<template>
<div>
My <AwesomeButton>UI button</AwesomeButton>!
<awesome-alert>Here's an alert!</awesome-alert>
</div>
</template>
它會自動導入僅在使用的元件,並且在更新 node_modules/awesome-ui/components/
中的元件時也支援 HMR。