この記事では、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と異なるので気になる方は参考にしてみてください。