画面は開発中のものです

人生とは、永遠のβテストだ。


121d3c318e49862e82dcdf3bf16e4529_s

PHPフレームワーク「Laravel」
この記事を書いている2018.6.14時点では、最新版は5.6系。

javascriptフレームワーク「Vue.js」
Laravel5.6.23の「package.json」を見る限り、採用されているのは2.5.7。

上記構成にて、web上に転がっている
「LaravelでVue.jsを動かしてみよう」的な記事のサンプルを動そうとしたところ、
意図した画面表示とならず、
ブラウザのコンソールに「Cannot find element」のエラーを吐いていたので、
対処法を備忘録として残しておきます。

このページに「書いていない」こと

このページでは、
・Laravelの環境構築
・Laravel上でVue.jsを動かすための環境構築
まわりの記述は割愛します。

私は以下のページなどを参考に環境構築しました。


サンプルコードでやろうとしていること

サンプルコードといっても、
/resources/assets/js/components/ 配下に配置されている
「ExampleComponent.vue」
に記述のHTMLを表示させるだけなのですが。

ちゃんと動けば、次のような画面が出るハズなんです。




しかし、
サンプルの通りに「testvue.blade.php」を作成し(まぁコピペなのだが)、




 # npm run dev

でビルドし、
「routes/web.php」でルーティングしたのですが、


Route::get('/testvue', function () {
    return view('testvue');
});

無情にも、まっしろい画面が出力されるだけなのでした……
(厳密にはcssが聞いているので#FFFFFFではないのですが)


Vue.jsのイベント発火タイミングが問題だった

ブラウザの管理コンソールを確認すると、
「Cannot find element」のエラー表示。

KOBA5884

(画面)要素が見つからない……だと……?

発生している事象としては、
「DOM操作したいのに操作する対象が見つからない……」といった感じ。
なるほど状況はわかった。しかし対処法がわからん。

困ったときは「フレームワーク + エラーメッセージ」でググってみましょう。
既に先人が同じようなことで困っているはずです。


なるほど、ページを描画する前にVue.jsで記述の処理を実行しようとしているのが問題なのだな。
どうにかして、「ページの読み込みが終わってから、javascriptの動作を実行させる」必要があります。


対処法1:js処理記述をイベントリスナで囲む

先ほどのページにて紹介の方法を試してみます。
javascriptの記述のタイミングは変えず、
処理の側で、「いつその処理を実行するのか」を記述します。


[app.js]
 document.addEventListener("DOMContentLoaded", function(event) {

// 元々記述のあった処理をaddEventListenerのカッコで挟む

 });

「画面要素の読み込みが終わったら、カッコ内の処理を実行するよ」
こうすることで、先ほど発生した、
「DOM操作したいのに操作する対象が見つからない……」
といった状況は回避できます。
操作したい画面要素を出力し切ってからの処理開始になるので。

対処法2:js読み込み後の発火タイミングをdeferで制御する

実はですね。
はじめに挙げたサンプルコードの時点で、
コードの読み込み順とイベントの発火順については、対処が為されていたのです。


以下、サンプルコードにてjavascriptを呼び出す際の記述の箇所なのですが、

[welcome.blade.php]
(前略)
<script src="js/app.js" defer></script>
(後略)

このように、scriptタグに読み込み対象のjavascriptファイルと一緒に「defer」と記述することで、
その呼び出したjavascriptのイベント発火タイミングを、
画面要素が全て描画し切った後に遅らせることが出来るのです。

これにより、通常はサンプルコードの通りに動かせば、
特に詰まることなく画面表示まで達成出来るハズなのでした。

 * * * 

なのに何故、私がサンプルコードを動かした際に、
「Cannot find element」エラーが発生してしまったのか。

実は、今回紹介したサンプルにたどり着く前に、
他のサイトなどで似たようなサンプルを拝見しつつ処理を試していたのですが、
その際に、「javascript呼び出し(deferなし)→画面要素描画」の手順を踏んでしまったらしく、
「Cannot find element」エラーが発生してしまっていたのでした。

その後、今回のサンプルに行き着き、模倣してみたのですが、
エラーは解消されず。
ブラウザのキャッシュ削除とかは試したはずなんだがなー……原因は不明です。
ただ、今回紹介した「対処1→対処2」の手順を踏むことで、
私の環境ではエラーは解消されました。

今回肝に刻んだ知見としては、
「DOM操作系のjavascriptを記述する際は、
読み込みのタイミングと処理のタイミングに気をつけようね」
ということ。

昔々に似たようなことでハマった覚えがあるのだけれども、
使っているフレームワークなどの仕様により、その辺りを勝手に解決してもらっていると、
久々にそうでない環境でコードを書いた際にハマってパニックになります……
このあたり、まだまだ鍛錬が足りて無いなぁ、といった感じです。
執筆者プロフィール

※この領域は現在工事中です

↑このページのトップヘ