Readouble

Livewire v3 ネスト

ネスト

多くの他のコンポーネントベースのフレームワークと同様に、Livewireコンポーネントはネスト可能です。つまり、1つのコンポーネントがその中に複数のコンポーネントをレンダリングできます。Like many other component-based frameworks, Livewire components are nestable — meaning one component can render multiple components within itself.

ただし、Livewireのネストシステムは他のフレームワークとは異なる方法で構築されているため、注意すべき特定の意味合いと制約があります。However, because Livewire's nesting system is built differently than other frameworks, there are certain implications and constraints that are important to be aware of.

lightbulb Tip: まずHydrationを理解する Livewireのネストシステムについて詳しく学ぶ前に、LivewireがコンポーネントをどのようにHydrateするかを完全に理解することが役立ちます。詳細については、hydration documentationをご覧ください。[!tip] Make sure you understand hydration first Before learning more about Livewire's nesting system, it's helpful to fully understand how Livewire hydrates components. You can learn more by reading the hydration documentation[/docs/hydration].

すべてのコンポーネントは孤立しているEvery component is an island

Livewireでは、ページ上のすべてのコンポーネントがその状態を追跡し、他のコンポーネントとは独立して更新を行います。In Livewire, every component on a page tracks its state and makes updates independently of other components.

たとえば、次のPostsとネストされたShowPostコンポーネントを考えてみましょう。For example, consider the following Posts and nested ShowPost components:

<?php

namespace App\Livewire;

use Illuminate\Support\Facades\Auth;
use Livewire\Component;

class Posts extends Component
{
    public $postLimit = 2;

    public function render()
    {
        return view('livewire.posts', [
            'posts' => Auth::user()->posts()
                ->limit($this->postLimit)->get(),
        ]);
    }
}
<div>
    Post Limit: <input type="number" wire:model.live="postLimit">

    @foreach ($posts as $post)
        <livewire:show-post :$post :key="$post->id">
    @endforeach
</div>
<?php

namespace App\Livewire;

use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use App\Models\Post;

class ShowPost extends Component
{
    public Post $post;

    public function render()
    {
        return view('livewire.show-post');
    }
}
<div>
    <h1>{{ $post->title }}</h1>

    <p>{{ $post->content }}</p>

    <button wire:click="$refresh">Refresh post</button>
</div>

初期ページロード時のコンポーネントツリー全体のHTMLは次のようになります。Here's what the HTML for the entire component tree might look like on initial page load:

<div wire:id="123" wire:snapshot="...">
    Post Limit: <input type="number" wire:model.live="postLimit">

    <div wire:id="456" wire:snapshot="...">
        <h1>The first post</h1>

        <p>Post content</p>

        <button wire:click="$refresh">Refresh post</button>
    </div>

    <div wire:id="789" wire:snapshot="...">
        <h1>The second post</h1>

        <p>Post content</p>

        <button wire:click="$refresh">Refresh post</button>
    </div>
</div>

親コンポーネントには、レンダリングされたテンプレートと、その中にネストされたすべてのコンポーネントのレンダリングされたテンプレートが含まれていることに注意してください。Notice that the parent component contains both its rendered template and the rendered templates of all the components nested within it.

各コンポーネントは独立しているため、それぞれが独自のIDとスナップショット(wire:idwire:snapshot)をHTMLに埋め込んでおり、LivewireのJavaScriptコアが抽出して追跡できるようになっています。Because each component is independent, they each have their own IDs and snapshots (wire:id and wire:snapshot) embedded in their HTML for Livewire's JavaScript core to extract and track.

いくつかの異なる更新シナリオを検討して、Livewireが異なるレベルのネストをどのように処理するかを確認しましょう。Let's consider a few different update scenarios to see the differences in how Livewire handles different levels of nesting.

子の更新Updating a child

show-postコンポーネントのいずれかで「Refresh post」ボタンをクリックすると、次のものがサーバに送信されます。If you were to click the "Refresh post" button in one of the child show-post components, here is what would be sent to the server:

{
    memo: { name: 'show-post', id: '456' },

    state: { ... },
}

返送されるHTMLは次のとおりです。Here's the HTML that would get sent back:

<div wire:id="456">
    <h1>The first post</h1>

    <p>Post content</p>

    <button wire:click="$refresh">Refresh post</button>
</div>

ここで重要なことは、子コンポーネントで更新がトリガーされた場合、そのコンポーネントのデータのみがサーバに送信され、そのコンポーネントのみが再レンダリングされることです。The important thing to note here is that when an update is triggered on a child component, only that component's data is sent to the server, and only that component is re-rendered.

次に、あまり直感的ではないシナリオである親コンポーネントの更新を見てみましょう。Now let's look at the less intuitive scenario: updating a parent component.

親の更新Updating the parent

念のため、親PostsコンポーネントのBladeテンプレートを次に示します。As a reminder, here's the Blade template of the parent Posts component:

<div>
    Post Limit: <input type="number" wire:model.live="postLimit">

    @foreach ($posts as $post)
        <livewire:show-post :$post :key="$post->id">
    @endforeach
</div>

ユーザーが「Post Limit」の値を2から1に変更すると、親でのみ更新がトリガーされます。If a user changes the "Post Limit" value from 2 to 1, an update will be solely triggered on the parent.

リクエストペイロードの例を次に示します。Here's an example of what the request payload might look like:

{
    updates: { postLimit: 1 },

    snapshot: {
        memo: { name: 'posts', id: '123' },

        state: { postLimit: 2, ... },
    },
}

ご覧のとおり、親Postsコンポーネントのスナップショットのみがサーバに送信されます。As you can see, only the snapshot for the parent Posts component is sent along to the server.

重要な質問は、「親コンポーネントが再レンダリングされ、子show-postコンポーネントに遭遇したときに何が起こるのか?リクエストペイロードにスナップショットが含まれていない場合、どのように子を再レンダリングするのか?」ということです。An important question you might be asking yourself is: what happens when the parent component re-renders and encounters the child show-post components? How will it re-render the children if their snapshots haven't been included in the request payload?

答えは「再レンダリングされない」です。The answer is: they won't be re-rendered.

LivewireがPostsコンポーネントをレンダリングすると、遭遇したすべての子コンポーネントのプレースホルダーをレンダリングします。When Livewire renders the Posts component, it will render placeholders for any child components it encounters.

上記の更新後のPostsコンポーネントのレンダリングされたHTMLの例を次に示します。Here is an example of what the rendered HTML for the Posts component might be after the above update:

<div wire:id="123">
    Post Limit: <input type="number" wire:model.live="postLimit">

    <div wire:id="456"></div>
</div>

postLimit1に更新されたため、1つの子のみがレンダリングされていることがわかります。ただし、完全な子コンポーネントの代わりに、一致するwire:id属性を持つ空の<div></div>のみがあることにも気づくでしょう。As you can see, only one child has been rendered because postLimit was updated to 1. However, you will also notice that instead of the full child component, there is only an empty <div></div> with the matching wire:id attribute.

このHTMLがフロントエンドで受信されると、Livewireはこのコンポーネントの古いHTMLをこの新しいHTMLに_morph_しますが、子コンポーネントのプレースホルダーはインテリジェントにスキップします。When this HTML is received on the frontend, Livewire will morph the old HTML for this component into this new HTML, but intelligently skip any child component placeholders.

その結果、_morphing_後、親Postsコンポーネントの最終的なDOMコンテンツは次のようになります。The effect is that, after morphing, the final DOM content of the parent Posts component will be the following:

<div wire:id="123">
    Post Limit: <input type="number" wire:model.live="postLimit">

    <div wire:id="456">
        <h1>The first post</h1>

        <p>Post content</p>

        <button wire:click="$refresh">Refresh post</button>
    </div>
</div>

パフォーマンスへの影響Performance implications

Livewireの「孤立」アーキテクチャは、アプリケーションにプラスとマイナスの両方の影響を与える可能性があります。Livewire's "island" architecture can have both positive and negative implications for your application.

このアーキテクチャの利点は、アプリケーションの高価な部分を分離できることです。たとえば、遅いデータベースクエリを独自の独立したコンポーネントに隔離でき、そのパフォーマンスのオーバーヘッドはページの残りの部分に影響を与えません。An advantage of this architecture is it allows you to isolate expensive portions of your application. For example, you can quarantine a slow database query to its own independent component, and its performance overhead won't impact the rest of the page.

ただし、このアプローチの最大の欠点は、コンポーネントが完全に分離されているため、コンポーネント間の通信/依存関係がより困難になることです。However, the biggest drawback of this approach is that because components are entirely separate, inter-component communication/dependencies becomes more difficult.

たとえば、上記の親PostsコンポーネントからネストされたShowPostコンポーネントにプロパティが渡された場合、それは「リアクティブ」ではありません。各コンポーネントは孤立しているため、親コンポーネントへのリクエストがShowPostに渡されるプロパティの値を変更しても、ShowPost内で更新されません。For example, if you had a property passed down from the above parent Posts component to the nested ShowPost component, it wouldn't be "reactive". Because each component is an island, if a request to the parent component changed the value of the property being passed into ShowPost, it wouldn't update inside ShowPost.

Livewireはこれらのハードルを克服し、リアクティブプロパティModelable componentsthe $parent objectなどのこれらのシナリオ専用のAPIを提供しています。Livewire has overcome a number of these hurdles and provides dedicated APIs for these scenarios like: Reactive properties[/docs/nesting#reactive-props], Modelable components[/docs/nesting#binding-to-child-data-using-wiremodel], and the $parent object[/docs/nesting#directly-accessing-the-parent-from-the-child].

ネストされたLivewireコンポーネントの動作方法に関するこの知識があれば、アプリケーション内でコンポーネントをいつ、どのようにネストするかについて、より多くの情報に基づいた意思決定を行うことができます。Armed with this knowledge of how nested Livewire components operate, you will be able to make more informed decisions about when and how to nest components within your application.

章選択

パッケージ

設定

バージョン変更
linkv3 linkv2
明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
OS表示
全OS表示
macOSのみ表示
windowsのみ表示
linuxのみ表示
JSフレームワーク
両フレームワーク
Reactのみ表示
Vueのみ表示
JSのみ表示

(JSが存在しない場合は、他を全表示)

和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作