---
title: "<NuxtPage>"
description: "<NuxtPage> 组件是显示位于 pages/ 目录中的页面所必需的。"
canonical_url: "https://nuxt.zhcndoc.com/docs/3.x/api/components/nuxt-page"
---
# \<NuxtPage>

> \<NuxtPage> 组件是显示位于 pages/ 目录中的页面所必需的。

`<NuxtPage>` 是 Nuxt 自带的内置组件。它可以让你显示位于 [`pages/`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/pages) 目录中的顶级或嵌套页面。

::note
`<NuxtPage>` 是 Vue Router 中 [`<RouterView>`](https://router.vuejs.org/api/interfaces/RouterViewProps.html#interface-routerviewprops) 的包装组件。应当使用它替代 `<RouterView>`，因为它会额外处理内部状态。否则，`useRoute()` 可能返回错误的路径。
::

`<NuxtPage>` 包含以下组件：

```vue
<template>
  <RouterView v-slot="{ Component }">
    <!-- 可选，当使用过渡动画时 -->
    <Transition>
      <!-- 可选，当使用 keep-alive 时 -->
      <KeepAlive>
        <Suspense>
          <component :is="Component" />
        </Suspense>
      </KeepAlive>
    </Transition>
  </RouterView>
</template>
```

默认情况下，Nuxt 不启用 `<Transition>` 和 `<KeepAlive>`。你可以在 nuxt.config 文件中启用它们，或者在 `<NuxtPage>` 上设置 `transition` 和 `keepalive` 属性。如果想为某个特定页面定义，可以在该页面组件中的 `definePageMeta` 中设置。

::warning
如果你在页面组件中启用了 `<Transition>`，请确保页面只有一个根元素。
::

由于 `<NuxtPage>` 底层使用了 `<Suspense>`，页面切换时组件的生命周期行为与普通的 Vue 应用不同。

在典型的 Vue 应用中，新的页面组件是在前一个完全卸载之后才挂载的。但在 Nuxt 中，由于 Vue `<Suspense>` 的实现机制，新的页面组件会在前一个页面卸载之前就先挂载。

## Props

- `name`：告知 `<RouterView>` 渲染匹配路由记录中对应名称的组件。
  - 类型：`string`
- `route`：带有所有已解析组件的路由位置对象。
  - 类型：`RouteLocationNormalized`
- `pageKey`：控制 `NuxtPage` 组件何时重新渲染。
  - 类型：`string` 或 `function`
- `transition`：定义所有通过 `NuxtPage` 渲染的页面的全局过渡效果。
  - 类型：`boolean` 或 [`TransitionProps`](https://vue.zhcndoc.com/api/built-in-components#transition)
- `keepalive`：控制通过 `NuxtPage` 渲染的页面状态是否保留。
  - 类型：`boolean` 或 [`KeepAliveProps`](https://vue.zhcndoc.com/api/built-in-components#keepalive)

::tip
Nuxt 会自动通过扫描并渲染 `/pages` 目录内所有 Vue 组件文件来解析 `name` 和 `route`。
::

## 示例

例如，如果你传入一个永远不变的 key，`<NuxtPage>` 组件只会渲染一次 —— 即首次挂载时。

```vue [app.vue]
<template>
  <NuxtPage page-key="static" />
</template>
```

你也可以基于当前路由使用动态 key：

```html
<NuxtPage :page-key="route => route.fullPath" />
```

::warning
不要在这里使用 `$route` 对象，因为它可能导致 `<NuxtPage>` 使用 `<Suspense>` 时渲染页面出现问题。
::

或者，可以在 `/pages` 目录中 Vue 组件的 `<script>` 部分通过 [`definePageMeta`](https://nuxt.zhcndoc.com/docs/3.x/api/utils/define-page-meta) 将 `pageKey` 作为 `key` 值传入。

```vue [pages/my-page.vue]
<script setup lang="ts">
definePageMeta({
  key: route => route.fullPath,
})
</script>
```

::link-example{to="https://nuxt.zhcndoc.com/docs/examples/routing/pages"}
::

## 页面组件的 Ref

要获取页面组件的 `ref`，可以通过 `ref.value.pageRef` 访问。

```vue [app.vue]
<script setup lang="ts">
const page = ref()

function logFoo () {
  page.value.pageRef.foo()
}
</script>

<template>
  <NuxtPage ref="page" />
</template>
```

```vue [my-page.vue]
<script setup lang="ts">
const foo = () => {
  console.log('foo 方法被调用')
}

defineExpose({
  foo,
})
</script>
```

## 自定义 Props

`<NuxtPage>` 也支持传递自定义 props，方便你将其逐级向下传递。

例如，在下面这个例子中，`foobar` 的值会传给 `NuxtPage`，然后传递给页面组件。

```vue [app.vue]
<template>
  <NuxtPage :foobar="123" />
</template>
```

你可以在页面组件中访问 `foobar` prop：

```vue [pages/page.vue]
<script setup lang="ts">
const props = defineProps<{ foobar: number }>()

console.log(props.foobar) // 输出: 123
</script>
```

如果没有用 `defineProps` 明确定义 prop，传给 `NuxtPage` 的任何 props 仍然可以从页面组件的 `attrs` 直接访问：

```vue [pages/page.vue]
<script setup lang="ts">
const attrs = useAttrs()
console.log(attrs.foobar) // 输出: 123
</script>
```

::read-more{to="https://nuxt.zhcndoc.com/docs/3.x/directory-structure/pages"}
::

---

- [源码](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/pages/runtime/page.ts)


## Sitemap

See the full [sitemap](https://nuxt.zhcndoc.com/sitemap.md) for all pages.
