ナビゲート
多くの現代的なウェブアプリケーションは、「シングルページアプリケーション」(SPA)として構築されています。これらのアプリケーションでは、アプリケーションによってレンダリングされる各ページは、完全なブラウザのページリロードを必要としなくなり、リクエストごとにJavaScriptとCSSアセットを再ダウンロードするオーバーヘッドを回避します。Many modern web applications are built as "single page applications" (SPAs). In these applications, each page rendered by the application no longer requires a full browser page reload, avoiding the overhead of re-downloading JavaScript and CSS assets on every request.
シングルページアプリケーションの代替は、マルチページアプリケーションです。これらのアプリケーションでは、ユーザーがリンクをクリックするたびに、完全に新しいHTMLページがリクエストされ、ブラウザでレンダリングされます。The alternative to a single page application is a multi-page application. In these applications, every time a user clicks a link, an entirely new HTML page is requested and rendered in the browser.
ほとんどのPHPアプリケーションは従来、マルチページアプリケーションでしたが、Livewireは、アプリケーション内のリンクに追加できるシンプルな属性wire:navigate
を介して、シングルページアプリケーションの体験を提供します。While most PHP applications have traditionally been multi-page applications, Livewire offers a single page application experience via a simple attribute you can add to links in your application: wire:navigate
.
基本的な使い方Basic usage
wire:navigate
の使用例を見てみましょう。以下は、3つのLivewireコンポーネントがルートとして定義された、典型的なLaravelルートファイル(routes/web.php
)です。Let's explore an example of using wire:navigate
. Below is a typical Laravel routes file (routes/web.php
) with three Livewire components defined as routes:
use App\Livewire\Dashboard;
use App\Livewire\ShowPosts;
use App\Livewire\ShowUsers;
Route::get('/', Dashboard::class);
Route::get('/posts', ShowPosts::class);
Route::get('/users', ShowUsers::class);
各ページのナビゲーションメニューの各リンクにwire:navigate
を追加することで、Livewireはリンククリックの標準的な処理を防ぎ、独自のより高速なバージョンに置き換えます。By adding wire:navigate
to each link in a navigation menu on each page, Livewire will prevent the standard handling of the link click and replace it with its own, faster version:
<nav>
<a href="/" wire:navigate>Dashboard</a>
<a href="/posts" wire:navigate>Posts</a>
<a href="/users" wire:navigate>Users</a>
</nav>
以下は、wire:navigate
リンクがクリックされたときに発生する処理の内訳です。Below is a breakdown of what happens when a wire:navigate
link is clicked:
- ユーザーがリンクをクリックしますUser clicks a link
- Livewireはブラウザが新しいページにアクセスするのを防ぎますLivewire prevents the browser from visiting the new page
- 代わりに、Livewireはバックグラウンドでページをリクエストし、ページ上部にローディングバーを表示しますInstead, Livewire requests the page in the background and shows a loading bar at the top of the page
- 新しいページのHTMLが受信されると、Livewireは現在のページのURL、
<title>
タグ、および<body>
の内容を新しいページの要素に置き換えますWhen the HTML for the new page has been received, Livewire replaces the current page's URL,<title>
tag and<body>
contents with the elements from the new page
この手法により、ページロード時間が大幅に短縮され(多くの場合2倍の速さ)、アプリケーションがJavaScriptで駆動されるシングルページアプリケーションのように「感じ」られます。This technique results in much faster page load times — often twice as fast — and makes the application "feel" like a JavaScript powered single page application.
リダイレクトRedirects
Livewireコンポーネントのいずれかがアプリケーション内の別のURLにユーザーをリダイレクトする場合、Livewireにwire:navigate
機能を使用して新しいページをロードするように指示することもできます。これを実現するには、redirect()
メソッドにnavigate
引数を指定します。When one of your Livewire components redirects users to another URL within your application, you can also instruct Livewire to use its wire:navigate
functionality to load the new page. To accomplish this, provide the navigate
argument to the redirect()
method:
return $this->redirect('/posts', navigate: true);
これで、新しいURLにユーザーをリダイレクトするために完全なページリクエストが使用される代わりに、Livewireは現在のページの内容とURLを新しいものに置き換えます。Now, instead of a full page request being used to redirect the user to the new URL, Livewire will replace the contents and URL of the current page with the new one.
リンクのプリフェッチPrefetching links
デフォルトでは、Livewireには、ユーザーがリンクをクリックする前にページをプリフェッチするための緩やかな戦略が含まれています。By default, Livewire includes a gentle strategy to prefetch pages before a user clicks on a link:
- ユーザーがマウスボタンを押し下げますA user presses down on their mouse button
- Livewireはページの要求を開始しますLivewire starts requesting the page
- 彼らはマウスボタンを放してクリックを完了しますThey lift up on the mouse button to complete the click
- Livewireはリクエストを完了し、新しいページに移動しますLivewire finishes the request and navigates to the new page
驚くべきことに、ユーザーがマウスボタンを押し下げて放すまでの時間は、サーバからページ全体、またはその半分をロードするのに十分な時間であることがよくあります。Surprisingly, the time between a user pressing down and lifting up on the mouse button is often enough time to load half or even an entire page from the server.
プリフェッチに対するさらに積極的なアプローチが必要な場合は、リンクに.hover
修飾子を使用できます。If you want an even more aggressive approach to prefetching, you may use the .hover
modifier on a link:
<a href="/posts" wire:navigate.hover>Posts</a>
.hover
修飾子は、ユーザーがリンクに60
ミリ秒間カーソルを合わせた後、Livewireにページをプリフェッチするように指示します。The .hover
modifier will instruct Livewire to prefetch the page after a user has hovered over the link for 60
milliseconds.
Warning! ホバー時のプリフェッチはサーバの使用量を増やします すべてのユーザーがカーソルを合わせたリンクをクリックするとは限らないため、
.hover
を追加すると、不要なページが要求されます。ただし、Livewireはページをプリフェッチする前に60
ミリ秒待機することで、このオーバーヘッドの一部を軽減しようとします。[!warning] Prefetching on hover increases server usage Because not all users will click a link they hover over, adding.hover
will request pages that may not be needed, though Livewire attempts to mitigate some of this overhead by waiting60
milliseconds before prefetching the page.
ページ訪問間で要素を永続化するPersisting elements across page visits
オーディオやビデオプレーヤーなど、ページロード間で永続化する必要があるユーザーインターフェイスのパーツがある場合があります。たとえば、ポッドキャストアプリケーションでは、ユーザーが他のページを閲覧しながらエピソードを聞き続けたい場合があります。Sometimes, there are parts of a user interface that you need to persist between page loads, such as audio or video players. For example, in a podcasting application, a user may want to keep listening to an episode as they browse other pages.
これは、Livewireで@persist
ディレクティブを使用して実現できます。You can achieve this in Livewire with the @persist
directive.
要素を@persist
でラップし、名前を付けることで、wire:navigate
を使用して新しいページが要求されたときに、Livewireは一致する@persist
を持つ新しいページの要素を探します。通常のように要素を置き換える代わりに、Livewireは新しいページの前のページの既存のDOM要素を使用し、要素内の状態を保持します。By wrapping an element with @persist
and providing it with a name, when a new page is requested using wire:navigate
, Livewire will look for an element on the new page that has a matching @persist
. Instead of replacing the element like normal, Livewire will use the existing DOM element from the previous page in the new page, preserving any state within the element.
以下は、@persist
を使用してページ間で永続化される<audio>
プレーヤー要素の例です。Here is an example of an <audio>
player element being persisted across pages using @persist
:
@persist('player')
<audio src="{{ $episode->file }}" controls></audio>
@endpersist
上記のHTMLが両方のページ(現在のページと次のページ)に表示される場合、元の要素は新しいページで再利用されます。オーディオプレーヤーの場合、あるページから別のページに移動しても、オーディオの再生は中断されません。If the above HTML appears on both pages — the current page, and the next one — the original element will be re-used on the new page. In the case of an audio player, the audio playback won't be interrupted when navigating from one page to another.
永続化された要素は、Livewireコンポーネントの外に配置する必要があることに注意してください。一般的な方法は、永続化された要素をメインレイアウト(resources/views/components/layouts/app.blade.php
など)に配置することです。Please be aware that the persisted element must be placed outside your Livewire components. A common practice is to position the persisted element in your main layout, such as resources/views/components/layouts/app.blade.php
.
<!-- resources/views/components/layouts/app.blade.php -->
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $title ?? 'Page Title' }}</title>
</head>
<body>
<main>
{{ $slot }}
</main>
@persist('player') <!-- [tl! highlight:2] -->
<audio src="{{ $episode->file }}" controls></audio>
@endpersist
</body>
</html>
アクティブなリンクの強調表示Highlighting active links
以下のように、サーバ側のBladeを使用して、ナビゲーションバーで現在アクティブなページリンクを強調表示することに慣れているかもしれません。You might be used to highlighting the currently active page link in a navbar using server-side Blade like so:
<nav>
<a href="/" class="@if (request->is('/')) font-bold text-zinc-800 @endif">Dashboard</a>
<a href="/posts" class="@if (request->is('/posts')) font-bold text-zinc-800 @endif">Posts</a>
<a href="/users" class="@if (request->is('/users')) font-bold text-zinc-800 @endif">Users</a>
</nav>
ただし、これらはページロード間で再利用されるため、永続化された要素内では機能しません。代わりに、Livewireのwire:current
ディレクティブを使用して、現在アクティブなリンクを強調表示する必要があります。However, this will not work inside persisted elements as they are re-used between page loads. Instead, you should use Livewire's wire:current
directive to highlight the currently active link.
現在アクティブなリンクに適用するCSSクラスをwire:current
に渡すだけです。Simply pass any CSS classes you want to apply to the currently active link to wire:current
:
<nav>
<a href="/dashboard" ... wire:current="font-bold text-zinc-800">Dashboard</a>
<a href="/posts" ... wire:current="font-bold text-zinc-800">Posts</a>
<a href="/users" ... wire:current="font-bold text-zinc-800">Users</a>
</nav>
これで、/posts
ページにアクセスすると、「Posts」リンクは他のリンクよりも強いフォント処理が適用されます。Now, when the /posts
page is visited, the "Posts" link will have a stronger font treatment than the other links.
詳細については、wire:current
ドキュメントをお読みください。Read more in the wire:current
documentation[/docs/wire-current].
スクロール位置の保持Preserving scroll position
デフォルトでは、Livewireはページ間を前後に移動するときにページのスクロール位置を保持します。ただし、ページロード間で永続化している個々の要素のスクロール位置を保持したい場合があります。By default, Livewire will preserve the scroll position of a page when navigating back and forth between pages. However, sometimes you may want to preserve the scroll position of an individual element you are persisting between page loads.
これを行うには、以下のように、スクロールバーを含む要素にwire:scroll
を追加する必要があります。To do this, you must add wire:scroll
to the element containing a scrollbar like so:
@persist('scrollbar')
<div class="overflow-y-scroll" wire:scroll> <!-- [tl! highlight] -->
<!-- ... -->
</div>
@endpersist
JavaScriptフックJavaScript hooks
各ページナビゲーションは、3つのライフサイクルフックをトリガーします。Each page navigation triggers three lifecycle hooks:
livewire:navigate
livewire:navigate
livewire:navigating
livewire:navigating
livewire:navigated
livewire:navigated
これらの3つのフックイベントは、すべてのタイプのナビゲーションでディスパッチされることに注意することが重要です。これには、Livewire.navigate()
を使用した手動ナビゲーション、ナビゲーションが有効になっているリダイレクト、およびブラウザの戻るボタンと進むボタンの押下が含まれます。It's important to note that these three hooks events are dispatched on navigations of all types. This includes manual navigation using Livewire.navigate()
, redirecting with navigation enabled, and back and forward button presses in the browser.
以下は、これらの各イベントのリスナを登録する例です。Here's an example of registering listeners for each of these events:
document.addEventListener('livewire:navigate', (event) => {
// ナビゲーションがトリガーされたときにトリガーされます。
// 「キャンセル」できます(ナビゲートが実際に実行されるのを防ぎます)。
event.preventDefault()
// ナビゲーションのトリガーに関する役立つコンテキストが含まれています。
let context = event.detail
// ナビゲーションの目的地のURLオブジェクト...
context.url
// これが、戻る/進む(履歴状態)ナビゲーションによってトリガーされたナビゲーションであるか
// どうかを示すブール値[true/false]...
context.history
// これのキャッシュされたバージョンがあるかどうかを示す
// ブール値[true/false]。ネットワークラウンドトリップを介して
// 新しいものをフェッチする代わりに...
context.cached
})
document.addEventListener('livewire:navigating', () => {
// 新しいHTMLがページに交換されようとしているときにトリガーされます...
// これは、ページがナビゲートされる前に
// HTMLを変化させるのに適した場所です...
})
document.addEventListener('livewire:navigated', () => {
// ページナビゲーションの最終ステップとしてトリガーされます...
// 「DOMContentLoaded」の代わりにページロード時にもトリガーされます...
})
[!warning] Event listeners will persist across pages
Warning! イベントリスナはページ間で永続化されますイベントリスナをドキュメントにアタッチすると、別のページに移動しても削除されません。これにより、特定のページに移動した後にのみコードを実行する必要がある場合、またはページごとに同じイベントリスナを追加する場合に、予期しない動作が発生する可能性があります。イベントリスナを削除しないと、存在しない要素を探している場合に他のページで例外が発生したり、ナビゲーションごとにイベントリスナが複数回実行されたりする可能性があります。When you attach an event listener to the document it will not be removed when you navigate to a different page. This can lead to unexpected behaviour if you need code to run only after navigating to a specific page, or if you add the same event listener on every page. If you do not remove your event listener it may cause exceptions on other pages when it's looking for elements that do not exist, or you may end up with the event listener executing multiple times per navigation.
イベントの実行後にイベントリスナを削除する簡単な方法は、
addEventListener
関数に3番目のパラメーターとしてオプション{once: true}
を渡すことです。An easy method to remove an event listener after it runs is to pass the option{once: true}
as a third parameter to theaddEventListener
function.document.addEventListener('livewire:navigated', () => { // ... }, { once: true })
新しいページの手動訪問Manually visiting a new page
wire:navigate
に加えて、JavaScriptを使用してLivewire.navigate()
メソッドを手動で呼び出して、新しいページへのアクセスをトリガーできます。In addition to wire:navigate
, you can manually call the Livewire.navigate()
method to trigger a visit to a new page using JavaScript:
<script>
// ...
Livewire.navigate('/new/url')
</script>
アナリティクスソフトウェアとの使用Using with analytics software
アプリでwire:navigate
を使用してページをナビゲートする場合、<head>
の <script>
タグは、ページが最初にロードされたときにのみ評価されます。When navigating pages using wire:navigate
in your app, any <script>
tags in the <head>
only evaluate when the page is initially loaded.
これにより、Fathom Analyticsなどのアナリティクスソフトウェアに問題が発生します。これらのツールは、最初のページ変更だけでなく、すべてのページ変更で<script>
スニペットが評価されることに依存しています。This creates a problem for analytics software such as Fathom Analytics[https://usefathom.com/]. These tools rely on a <script>
snippet being evaluated on every single page change, not just the first.
Google Analyticsなどのツールは、これを自動的に処理するのに十分なほどスマートですが、Fathom Analyticsを使用する場合は、各ページのアクセスが適切に追跡されるように、data-spa="auto"
をスクリプトタグに追加する必要があります。Tools like Google Analytics[https://marketingplatform.google.com/about/analytics/] are smart enough to handle this automatically, however, when using Fathom Analytics, you must add data-spa="auto"
to your script tag to ensure each page visit is tracked properly:
<head>
<!-- ... -->
<!-- Fathom Analytics -->
@if (! config('app.debug'))
<script src="https://cdn.usefathom.com/script.js" data-site="ABCDEFG" data-spa="auto" defer></script> <!-- [tl! highlight] -->
@endif
</head>
スクリプトの評価Script evaluation
wire:navigate
を使用して新しいページにナビゲートすると、ブラウザがページを変更したように感じられます。ただし、ブラウザの観点から見ると、厳密には元のページにとどまっています。When navigating to a new page using wire:navigate
, it feels like the browser has changed pages; however, from the browser's perspective, you are technically still on the original page.
このため、スタイルとスクリプトは最初のページで通常どおりに実行されますが、後続のページでは、通常JavaScriptを記述する方法を調整する必要がある場合があります。Because of this, styles and scripts are executed normally on the first page, but on subsequent pages, you may have to tweak the way you normally write JavaScript.
以下に、wire:navigate
を使用する場合に注意すべきいくつかの注意点とシナリオを示します。Here are a few caveats and scenarios you should be aware of when using wire:navigate
.
DOMContentLoaded
に依存しないDon't rely on DOMContentLoaded
コードを実行するページが完全にロードされた後にのみ実行されるように、JavaScriptをDOMContentLoaded
イベントリスナ内に配置するのが一般的な方法です。It's common practice to place JavaScript inside a DOMContentLoaded
event listener so that the code you want to run only executes after the page has fully loaded.
wire:navigate
を使用する場合、DOMContentLoaded
は最初のページアクセスでのみトリガーされ、後続のアクセスではトリガーされません。When using wire:navigate
, DOMContentLoaded
is only fired on the first page visit, not subsequent visits.
すべてのページアクセスでコードを実行するには、DOMContentLoaded
のすべてのインスタンスをlivewire:navigated
と交換します。To run code on every page visit, swap every instance of DOMContentLoaded
with livewire:navigated
:
document.addEventListener('DOMContentLoaded', () => { // [tl! remove]
document.addEventListener('livewire:navigated', () => { // [tl! add]
// ...
})
これで、このリスナ内に配置されたコードは、最初のページアクセス時、およびLivewireが後続のページへのナビゲートを完了した後に実行されます。Now, any code placed inside this listener will be run on the initial page visit, and also after Livewire has finished navigating to subsequent pages.
このイベントをリッスンすることは、サードパーティライブラリを初期化するような場合に役立ちます。Listening to this event is useful for things like initializing third-party libraries.
<head>
のスクリプトは1回ロードされますScripts in <head>
are loaded once
2つのページが<head>
に同じ<script>
タグを含んでいる場合、そのスクリプトは最初のページアクセスでのみ実行され、後続のページアクセスでは実行されません。If two pages include the same <script>
tag in the <head>
, that script will only be run on the initial page visit and not on subsequent page visits.
<!-- 1ページ目 -->
<head>
<script src="/app.js"></script>
</head>
<!-- 2ページ目 -->
<head>
<script src="/app.js"></script>
</head>
新しい<head>
スクリプトが評価されますNew <head>
scripts are evaluated
後続のページに、最初のページアクセス時の<head>
に存在しなかった新しい<script>
タグが<head>
に含まれている場合、Livewireは新しい<script>
タグを実行します。If a subsequent page includes a new <script>
tag in the <head>
that was not present in the <head>
of the initial page visit, Livewire will run the new <script>
tag.
以下の例では、2ページ目には、サードパーティツール用の新しいJavaScriptライブラリが含まれています。ユーザーが2ページ目に移動すると、そのライブラリが評価されます。In the below example, page two includes a new JavaScript library for a third-party tool. When the user navigates to page two, that library will be evaluated.
<!-- 1ページ目 -->
<head>
<script src="/app.js"></script>
</head>
<!-- 2ページ目 -->
<head>
<script src="/app.js"></script>
<script src="/third-party.js"></script>
</head>
Info: ヘッドアセットはブロッキングされる
<head>
タグ内に<script src="...">
のようなアセットを含む新しいページに移動する場合、そのアセットはフェッチされ処理されてからナビゲーションが完了し、新しいページが入れ替わります。これは意外な動作かもしれませんが、これらのアセットに依存するスクリプトがすぐにアクセスできるようにするためです。[!info] Head assets are blocking If you are navigating to a new page that contains an asset like<script src="...">
in the head tag. That asset will be fetched and processed before the navigation is complete and the new page is swapped in. This might be surprising behavior, but it ensures any scripts that depend on those assets will have immediate access to them.
アセット変更時のリロードReloading when assets change
アプリケーションのメインの JavaScript ファイル名にバージョンハッシュを含めることは一般的な方法です。これにより、アプリケーションの新しいバージョンをデプロイした後、ユーザーはブラウザのキャッシュから提供される古いバージョンではなく、最新の JavaScript アセットを受け取ることができます。It's common practice to include a version hash in an application's main JavaScript file name. This ensures that after deploying a new version of your application, users will receive the fresh JavaScript asset, and not an old version served from the browser's cache.
しかし、wire:navigate
を使用し、各ページへのアクセスが新しいブラウザページのロードではなくなったため、ユーザーはデプロイ後も古い JavaScript を受け取っている可能性があります。But, now that you are using wire:navigate
and each page visit is no longer a fresh browser page load, your users may still be receiving stale JavaScript after deployments.
これを防ぐために、<head>
内の<script>
タグにdata-navigate-track
を追加できます。To prevent this, you may add data-navigate-track
to a <script>
tag in <head>
:
<!-- Page one -->
<head>
<script src="/app.js?id=123" data-navigate-track></script>
</head>
<!-- Page two -->
<head>
<script src="/app.js?id=456" data-navigate-track></script>
</head>
ユーザーが page two にアクセスすると、Livewire は新しい JavaScript アセットを検出し、ブラウザのページ全体のリロードをトリガーします。When a user visits page two, Livewire will detect a fresh JavaScript asset and trigger a full browser page reload.
Laravel's Vite plug-in を使用してアセットをバンドルおよび提供している場合、Livewire はレンダリングされた HTML アセットタグにdata-navigate-track
を自動的に追加します。通常どおりアセットとスクリプトを参照し続けることができます。If you are using Laravel's Vite plug-in[https://laravel.com/docs/vite#loading-your-scripts-and-styles] to bundle and serve your assets, Livewire adds data-navigate-track
to the rendered HTML asset tags automatically. You can continue referencing your assets and scripts like normal:
<head>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
Livewire は、レンダリングされた HTML タグに自動的にdata-navigate-track
を挿入します。Livewire will automatically inject data-navigate-track
onto the rendered HTML tags.
Warning! クエリ文字列の変更のみが追跡される Livewire は、
[data-navigate-track]
要素のクエリ文字列(?id="456"
)が変更された場合にのみページをリロードし、URI 自体(/app.js
)はリロードしません。[!warning] Only query string changes are tracked Livewire will only reload a page if a[data-navigate-track]
element's query string (?id="456"
) changes, not the URI itself (/app.js
).
<body>
内のスクリプトは再評価されるScripts in the <body>
are re-evaluated
Livewire は新しいページごとに<body>
の内容全体を置き換えるため、新しいページのすべての<script>
タグが実行されます。Because Livewire replaces the entire contents of the <body>
on every new page, all <script>
tags on the new page will be run:
<!-- Page one -->
<body>
<script>
console.log('Runs on page one')
</script>
</body>
<!-- Page two -->
<body>
<script>
console.log('Runs on page two')
</script>
</body>
<body>
内に一度だけ実行したい<script>
タグがある場合は、<script>
タグにdata-navigate-once
属性を追加すると、Livewire は最初のページへのアクセス時のみに実行します。If you have a <script>
tag in the body that you only want to be run once, you can add the data-navigate-once
attribute to the <script>
tag and Livewire will only run it on the initial page visit:
<script data-navigate-once>
console.log('Runs only on page one')
</script>
プログレスバーのカスタマイズCustomizing the progress bar
ページのロードに 150ms より長くかかる場合、Livewire はページの上部にプログレスバーを表示します。When a page takes longer than 150ms to load, Livewire will show a progress bar at the top of the page.
Livewire の設定ファイル(config/livewire.php
)内で、このバーの色をカスタマイズしたり、完全に無効にしたりできます。You can customize the color of this bar or disable it all together inside Livewire's config file (config/livewire.php
):
'navigate' => [
'show_progress_bar' => false,
'progress_bar_color' => '#2299dd',
],