 
                Laravelの変数をVueに渡す方法
この記事では、Laravelに一部Vueを導入している際にLaravelでの変数をVueに渡す方法を紹介します。
Inertia.jsを使っていると、Controllerから簡単に値を渡すことができますが、Vueを部分的に導入しているとLaravel側の変数をVue側に渡すには一工夫必要です。
方法はいくつかありますが、私が試した方法が参考になれば幸いです。
この記事を読むメリット
- 部分的に導入しているVueにLaravelから値を渡す方法が分かる
前提:Laravelに一部Vueを導入している
今回は、Laravelに一部Vueを導入している前提で進めていきます。
app.jsは以下のように設定してあります。
import { createApp } from "vue";
import ExampleComponent from "./components/ExampleComponent.vue";
import AnotherComponent from "./components/AnotherComponent.vue";
// コンポーネントのマッピング
const components = [
    {
        id: "example-app",
        component: ExampleComponent,
    },
    {
        id: "another-app",
        component: AnotherComponent,
    },
    // 新しいコンポーネントが必要な場合はここに追加
];
// コンポーネントを動的にマウントする関数
const mountComponent = ({ id, component }) => {
    const element = document.getElementById(id);
    if (element) {
        const app = createApp(component);
        app.mount(`#${id}`);
    }
};
// 各コンポーネントをループで処理
components.forEach(mountComponent);上記の記事で詳しく解説していますが、以下のような仕組みでVueを動作させています。
- Vueコンポーネントとそれに対応するDOM要素のidをオブジェクトとして作成
- コンポーネントを動的にマウントする関数「mountComponent」を定義
- マッピングした配列をループしてmountComponent関数を実行
こうすることで、blade側では以下のような記述で、idに紐づくコンポーネントを表示させることができます。
<div id="example-app" data-props='@json($vueData)'></div>このような設定がしてある前提で進めていきます。
bladeにVueをそのまま書く方法もありますが、今回は上記のようにVueファイルを使って導入している前提です。
Laravel側の変数をVueに渡す方法
ここから実際にLaravel側の変数をVueに渡す方法を紹介していきます。
まずは手順を簡単に整理します。
- Controller側で変数を配列で渡す
- Blade内でLaravelから渡されたデータをデータ属性として埋め込む
- app.js内でコンポーネントにデータを渡す
- 各コンポーネントでpropsを受け取る
それでは1つずつ解説していきます。
Controller側で変数を配列で渡す
まずはLaravelのController側で変数を渡します。
public function dashboard()
{
    $vueData = [
        'message' => 'Hello, Vue!',
        'user' => [
            'name' => 'Sample User',
            'email' => 'test@test.com',
            ]
    ];
    return view('dashboard')
        ->with('vueData', $vueData);
}blade側で個々の変数を配列に入れても良いですが、今回はController側で配列にしてbladeに渡しています。
配列$vueDataがbladeに渡されます。
ここはLaravel側のことなので細かい説明は省きます。
Blade内でLaravelから渡されたデータをデータ属性として埋め込む
続いてはblade側でContollerから渡したデータを埋め込みます。
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Dashboard') }}
        </h2>
    </x-slot>
    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div id="example-app" data-props='@json($vueData)'></div>
        </div>
    </div>
</x-app-layout>
ポイントは「<div id=”example” data-props=’@json($vueData)’></div>」の部分です。
id要素が「example」の要素でExampleComponentがレンダリングされるので、その要素に渡したいデータを「data-props」として渡します。
js側にデータを送る際はJSON形式にする必要があるので「@json($vueData)」にします。
Laravel 8.40.0以降を使用している方は「@js()」の方が推奨みたいです。
バージョンを確認して推奨される方をお使いください。
app.js内でコンポーネントにデータを渡す
続いては各コンポーネントにデータを渡すためにapp.jsで設定をします。
app.jsを以下のように設定します。
import { createApp, h } from "vue";
import ExampleComponent from "./components/ExampleComponent.vue";
import AnotherComponent from "./components/AnotherComponent.vue";
// コンポーネントのマッピング
const components = [
    {
        id: "example-app",
        component: ExampleComponent,
    },
    {
        id: "another-app",
        component: AnotherComponent,
    },
    // 新しいコンポーネントが必要な場合はここに追加
];
// コンポーネントを動的にマウントする関数
const mountComponent = ({ id, component }) => {
    const element = document.getElementById(id);
    if (element) {
        const props = element.getAttribute("data-props");
        const parsedProps = props ? JSON.parse(props) : {};
        const app = createApp({
            render: () => h(component, { data: parsedProps }),
        });
        app.mount(`#${id}`);
    }
};
// 各コンポーネントをループで処理
components.forEach(mountComponent);
「const props = container.getAttribute(“data-props”);」ここで対象のid要素に「data-props」属性があればそのデータを取得します。
続いてデータ属性でセットされた値は文字列として扱われるため、JavaScriptオブジェクトに変換するする必要があるので「JSON.parse(props)」でパースします。
「const app = createApp({render: () => h(component, { data: parsedProps }),});」で、パースされたJavaScriptオブジェクトをコンポーネントに渡しています。
あとはcomponentsをループしてマウントしていきます。
これで各コンポーネントにデータを送ることができているはずです。
各コンポーネントでpropsを受け取る
続いては渡されたコンポーネント内でデータを受け取り使っていきます。
<template>
    <div>
        <h1>Hello, Vue!</h1>
        <p>{{ data.message }}</p>
    </div>
</template>
<script>
export default {
    name: "ExampleComponent",
    props: {
        data: {
            type: Object,
            required: true,
        },
    },
    mounted() {
        console.log(this.data);
    },
};
</script>
<style scoped>
h1 {
    color: blue;
}
</style>
ExampleComponentの引数でpropsとして渡されたデータを受け取ります。
コンソールにも渡ってきたデータを確認したいのでその記述も入れています。
本来であれば存在チェックなどが必要ですが、ここでは省いています。
コンソールにpropsを出力していますが、きちんと渡した値が取得できていることが確認できます。

これでLaravelから渡した値をVueで利用することができるようになりました!
一部Vueで実装したい場合に便利
いかがだったでしょうか。
これでLaravelからのデータをVueでも利用することができると思います。
app.js内で各コンポーネントのレンダリングをまとめているので複数のコンポーネントを利用したい場合にも汎用が効くかと思います。
方法は他にもあるかと思いますが、参考になれば幸いです。
これのReactバージョンは以下記事で解説しています。
やり方は同じですが、書き方がVueと異なるので気になる方は参考にしてみてください。
 
                        

 
			 
			 
			 
			 
			 
			 
                