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レスポンスを返すことでページをレンダリングできます。 この例では、このページが resources/js/Pages/User/Show.vue
Laravelアプリケーション内に保存されていると仮定します。
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コンポーネントです。
レイアウトをページコンポーネントの子として実装するのは簡単ですが、訪問間でレイアウトインスタンスが破棄されて再作成されることになります。 つまり、ページ間を移動するときに永続的なレイアウト状態を持つことはできません。
たとえば、ポッドキャストWebサイトにオーディオプレーヤーがあり、ユーザーがサイト内を移動しても再生を続けたい場合があります。 あるいは、ページ訪問間でサイドバーナビゲーションのスクロール位置を単に維持したい場合があります。 これらの状況では、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
に設定されます。
resolve()
コールバックで使用可能なページのname
に基づいて、デフォルトのページレイアウトを条件付きで設定することもできます。 たとえば、デフォルトのレイアウトをパブリックページに適用したくない場合があります。
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
},
// ...
})