页面

使用 Inertia 构建应用程序时,您的应用程序中的每个页面通常都有自己的控制器/路由和相应的 JavaScript 组件。这使您可以仅检索该页面所需的数据 - 无需 API。

此外,页面所需的所有数据都可以在浏览器渲染页面之前检索,从而无需在用户访问您的应用程序时显示“加载”状态。

创建页面

Inertia 页面只是 JavaScript 组件。如果您曾经编写过 Vue、React 或 Svelte 组件,您会感觉宾至如归。正如您在下面的示例中看到的,页面从您的应用程序的控制器接收数据作为 props。

<script setup>
import Layout from './Layout'
import { Head } from '@inertiajs/vue3'

defineProps({ user: Object })
</script>

<template>
  <Layout>
    <Head title="Welcome" />
    <h1>Welcome</h1>
    <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
  </Layout>
</template>

鉴于上面的页面,您可以通过从控制器或路由返回一个 Inertia 响应 来渲染页面。在这个例子中,让我们假设这个页面存储在 Laravel 应用程序中的 resources/js/Pages/User/Show.vue 中。

use Inertia\Inertia;

class UserController extends Controller
{
    public function show(User $user)
    {
        return Inertia::render('User/Show', [
          'user' => $user
        ]);
    }
}

创建布局

虽然不是必需的,但对于大多数项目来说,创建所有页面都可以扩展的站点布局是有意义的。您可能已经注意到,在我们上面的页面示例中,我们将页面内容包装在 <Layout> 组件中。以下是一个此类组件的示例

<script setup>
import { Link } from '@inertiajs/vue3'
</script>

<template>
  <main>
    <header>
      <Link href="/">Home</Link>
      <Link href="/about">About</Link>
      <Link href="/contact">Contact</Link>
    </header>
    <article>
      <slot />
    </article>
  </main>
</template>

如您所见,此模板中没有 Inertia 特定的内容。这只是一个典型的 Vue 组件。

持久布局

虽然将布局作为页面组件的子级来实现很简单,但这会强制布局实例在访问之间被销毁和重新创建。这意味着您在页面之间导航时无法拥有持久布局状态。

例如,也许您在播客网站上有一个音频播放器,您希望它在用户浏览网站时继续播放。或者,也许您只是想在页面访问之间维护侧边栏导航中的滚动位置。在这些情况下,解决方案是利用 Inertia 的持久布局。

<script>
import Layout from './Layout'

export default {
  // Using a render function...
  layout: (h, page) => h(Layout, [page]),

  // Using shorthand syntax...
  layout: Layout,
}
</script>

<script setup>
defineProps({ user: Object })
</script>

<template>
  <H1>Welcome</H1>
  <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
</template>

您还可以使用嵌套布局创建更复杂的布局安排。

<script>
import SiteLayout from './SiteLayout'
import NestedLayout from './NestedLayout'

export default {
  // Using a render function...
  layout: (h, page) => {
    return h(SiteLayout, () => h(NestedLayout, () => page))
  },

  // Using the shorthand...
  layout: [SiteLayout, NestedLayout],
}
</script>

<script setup>
defineProps({ user: Object })
</script>

<template>
  <H1>Welcome</H1>
  <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
</template>

如果您使用的是 Vue 2.7 或 Vue 3,您可以选择使用 defineOptions 插件<script setup> 中定义布局

<script setup>
import Layout from './Layout'

defineOptions({ layout: Layout })
</script>

默认布局

如果您使用的是持久布局,您可能会发现,在应用程序主 JavaScript 文件的 resolve() 回调中定义默认页面布局很方便。

import Layout from './Layout'

createInertiaApp({
  resolve: name => {
    const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
    let page = pages[`./Pages/${name}.vue`]
    page.default.layout = page.default.layout || Layout
    return page
  },
  // ...
})

如果尚未为该页面设置布局,这将自动将页面布局设置为 Layout

您甚至可以更进一步,根据页面 name 有条件地设置默认页面布局,该名称可用于 resolve() 回调。例如,也许您不希望默认布局应用于您的公共页面。

import Layout from './Layout'

createInertiaApp({
  resolve: name => {
    const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
    let page = pages[`./Pages/${name}.vue`]
    page.default.layout = name.startsWith('Public/') ? undefined : Layout
    return page
  },
  // ...
})