作成日:2021/04/12 更新日:2022/01/27
#3 Veu.jsをCDNで読み込み画面表示させる
Vue.jsの使い方
前回、「応用2」で簡単なWebアプリケーションを作りました。PHPを使ってデータベースに接続し、取得されたデータを配列として変数に入れ、その配列変数をforeach文で回し、 echoを使ってHTMLとして表示させていました。
それをVue.jsを使って表示することも可能です。
Vue.jsを使うことで、その後の操作が同じ言語のJavaScriptで済みますので、 ページの移動や再読み込みが少ない、ユーザーの利便性を高めたWebサイト*1を作るのに適しています。 また、データベースから取得したデータをJSON形式*2にするのがポイントです。
今回は動的なサイトをつくるというより、PHPで実装した内容をVue.jsを使ってみようという趣旨ですので、 本来のVue.jsの機能は十分に発揮されませんが、まずはVue.jsアプリケーションを体感してみましょう。
#4 PHP(echo)の代わりにVue.jsでHTML表示
Vue.jsのインストール
まず応用2で作った名前移動アプリ[sortable3]をコピーして[sortable4]を作ります。※ファイルがない場合はダウンロード
Veu.jsをCDNで読み込みます。
<head>
・・・
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
</head>
<head>タグの中にスクリプトタグを記述します。Veu.js使う準備はこれだけです。データベースから取得したデータをJSON形式に変換してvue.jsにデータをわたす
応用2で作ったアプリケーションでは、データの取得と表示を以下のように書きました。index.php
<div id="drag-area">
<?php
$sql = '
SELECT
t1.*,
genders.gender
FROM
sortable AS t1
LEFT JOIN `genders` ON t1.gender_id = genders.id
';
$result = $select->select($sql);
foreach ($result as $val){
echo ' <div class="drag gender'.$val['gender_id'].'" data-num="'.$val['id'].'" style="left:'.$val['left_x'].'px; top:'.$val['top_y'].'px;">'.PHP_EOL;
echo ' <p><span class="name">'.$val['id'].' '.$val['name'].' ('.$val['gender'].')</span></p>'.PHP_EOL;
echo ' </div>'.PHP_EOL;
}
?>
</div>
これを以下のように追加・変更します。
<div id="drag-area">
<?php
$sql = '
SELECT
t1.*,
genders.gender
FROM
sortable AS t1
LEFT JOIN `genders` ON t1.gender_id = genders.id
';
$result = $select->select($sql);
/* PHPで取得したデータをJSON形式に変換 */
$json_data = json_encode( $stmt, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
/* 表示はvue.jsにまかせます。
foreach ($result as $val){
echo ' <div class="drag gender'.$val['gender_id'].'" data-num="'.$val['id'].'" style="left:'.$val['left_x'].'px; top:'.$val['top_y'].'px;">'.PHP_EOL;
echo ' <p><span class="name">'.$val['id'].' '.$val['name'].' ('.$val['gender'].')</span></p>'.PHP_EOL;
echo ' </div>'.PHP_EOL;
}
*/
?>
<div
v-for="item in jsonData"
v-bind:key="item.id"
class="drag"
v-bind:class="'gender' + item.gender_id"
v-bind:data-num="item.id"
v-bind:style="'left:' + item.left_x + 'px; top:' + item.top_y + 'px;'"
>
<p><span class="name">{{item.id}} {{item.name}} ({{item.gender}})</span></p>
</div>
</div>
<script>
/* PHPのデータをからJSにJSONデータとして変換させる */
let jsonData = JSON.parse('<?= $json_data; ?>');
new Vue({
el : '#drag-area',
data: {jsonData}
});
</script>
PHPはデータ取得のみの機能になり、データを表示するVue.jsの設定と、表示させるHTMLタグが登場しました。
その① データベースからデータの取得
取得したデータをJSON形式に変換
$json_data = json_encode( $stmt, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
データ取得部分のSQL文は同じですが、データ取得後にJSON化させて$json_data変数に格納しています。json_encode()関数を使って、連想配列をJSON化(エンコード)します。
○第一引数には、対象となる変数$stmtを指定します。
○第二引数には、文字をエスケープさせるオプションを4つ指定します。
JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT
エスケープされたJSONデータの内容は以下のような文字列になります。print_r()関数で確認してみましょう。
{"id":9, "name":"\u5c71\u7530\u5b5d\u4e4b", "left_x":37, "top_y":273, "gender_id":1, "gender":"\u7537\u6027"},{...
データベースの内容が "id":9 のように {"キー名" : 値} の関係で取得されます。
日本語はエスケープされているので、見慣れない文字列になっているのが確認できます。
その② Vue.jsの出力部分
<div
v-for="item in jsonData"
v-bind:key="item.id"
class="drag"
v-bind:class="'gender' + item.gender_id"
v-bind:data-num="item.id"
v-bind:style="'left:' + item.left_x + 'px; top:' + item.top_y + 'px;'"
>
<p><span class="name">{{item.id}} {{item.name}} ({{item.gender}})</span></p>
</div>
データ表示部分です。Vue.jsを使って表示(レンダリング)させています。見慣れない属性タグや、Vue.jsテンプレート構文の{{ }}でデータを出力しているのが特徴的ですね。 属性タグは見やすいように改行していますが、1行で書いてもかまいません。
○属性タグ
①v-for ディレクティブと呼ばれるもので、 "エイリアス名 for データ"の書き方で、 jsonData に入っている配列データの中からひとつづつのデータを指すために、itemという名前の”エイリアス”を作り、反復処理させるものです。
phpのforeachのようなものです。ディレクティブとは(命令する)という意味です。Vue.js独自の属性タグのことです。
②v-bind ディレクティブと呼ばれており、 html属性タグで出力・更新するときに使います。 固定されたclassがある場合は、上記のように分けて記載しましょう。
また、文字のあとにデータをバインドさせる場合は 文字列を' 'で囲って+でつなぎます。
③属性タグの属性値はエイリアス.キーでJSONデータの値をバインドさせます。
上の例では、itemというエイリアスのなかにあるキー「gender_id」を指定してありその値が出力されます。v-bind:keyは必ず必要です。
○テンプレート
④HTML内にテキスト表示させる場合は、{{ }}(マスタッシュタグ)にいれて、{{エイリアス.キー}}で出力。 ユーザーの操作に合わせて内容が変更されるため、データバインディング(データを紐付ける)と呼ばれています。
その③ Vue.jsの設定部分
<script>
/* PHPのデータをJavaScriptへ渡す処理です。 */
let jsonData = JSON.parse('<?= $json_data; ?>');
/* vueインスタンスを作成 */
new Vue({
el : '#drag-area',
data: {jsonData}
});
</script>
JSON.parse() メソッドを使うと、文字列(PHPでechoしたJSON形式の文字列)を、{ }で囲われているデータの集まりである、 JavaScriptオブジェクトに変換します。parseとは「解析する」という意味です。
jsonDataという名前の変数に入れておきます。
new Vue()のところはVueの設定部分です。
new Vue()でインスタンスを作成するときは、オプションの Vue()関数で Vue インスタンスを作成して新しいオブジェクトを作り、{ }内にオプションを付けていきます。
オプションdataプロパティにはPHP→jsで変換取得したjsonDataを入れます。データは連想配列なので{ }の中に入れます。
注)new Vue()でインスタンスを作成する場合は、elプロパティに設定している要素(ここでは #drag-area)が読み込まれたあと(下部)に記述しなければなりません。
※配列を展開してみた場合
<script>
new Vue({
el : '#drag-area',
data: {
jsonData:[
{id:1, gender:"男性", gender_id:1, name:"下北太郎", left_x:10, top_y:15},
{id:2, gender:"男性", gender_id:1, name:"下北次郎", left_x:20, top_y:12},
{id:3, gender:"女性", gender_id:2, name:"下北三郎", left_x:43, top_y:82},
{id:4, gender:"男性", gender_id:1, name:"下北四郎", left_x:56, top_y:47},
{キー:値, キー:値, ... }
]
}
});
</script>
仮にdata: {jsonData}の部分が展開された場合は、このような内容になります。実際の表示
#5 vueコンポーネントでHTML表示させる
Vue.jsにはcomponentという考え方があり、 簡単にいえばコンポーネントとよばれる部品を作り、HTMLのなかで出力する方法です。今回のサンプルプログラムには向いていませんが、複数の同じようなレイアウトの画面を作る際に適しています。 ここでは、コンポーネントのさわりをやってみましょう。
index.phpをコピーしてtest.phpを作り、以下のように、データを変更してみましょう。
<div
v-for="item in jsonData"
v-bind:key="item.id"
class="drag"
v-bind:class="'gender' + item.gender_id"
v-bind:data-num="item.id"
v-bind:style="'left:' + item.left_x + 'px; top:' + item.top_y + 'px;'"
>
<p><span class="name">{{item.id}} {{item.name}} ({{item.gender}})</span></p>
</div>
index.phpのこの部分を
<child-component
v-for="item in jsonData"
v-bind:key="item.id"
v-bind:item="item"
></child-component>
新しくこのように変えてみましょうhtmlではdivではなく、独自に作ったHTMLタグ(テンプレートタグ)を入れます。
一部のv-bind設定は記述していくと長くなるので、コンポーネント設定のtemplete:側に移動しています。
また、v-bind:itemと宣言し、 データを参照しているエイリアス名を入れ、vueインスタンスで設定したdataプロパティの内容をバインド(連動)させています。
<script>
new Vue({
el : '#drag-area',
data: {jsonData}
});
</script>
この部分を以下の内容に変更
<script>
/* コンポーネント変数の設定 */
let ComponentData = {
props: ['item'],
template: `
<div class="drag"
v-bind:class="'gender' + item.gender_id"
v-bind:data-num="item.id"
v-bind:style="'left:' + item.left_x + 'px; top:' + item.top_y + 'px;'"
>
<p><span class="name">{{item.id}} {{item.name}} ({{item.gender}})</span></p>
</div>
`
}
/* Vueインスタンス設定 */
new Vue({
el : '#drag-area',
data: {jsonData},
/* コンポーネント変数の登録 */
components: {
'child-component': ComponentData
}
});
</script>
Vue.jsの方では、let 変数名 = {}でコンポーネントを作ります。props: にプロパティを登録します。 template: で記述したコンポーネントが、HTMLに挿入されます。
Vue()関数の中に、あらたにcomponents: プロパティを追加します。
components: {'コンポーネント名' : コンポーネント変数} とし、コンポーネント表示部分にコンポーネントデータを渡します。
このようにコンポーネントを用いても表示されることが確認できます。
コンポーネントを理解する
試しに以下のような画面表示になるものを作ってみたとします。表示 htmlコード index3.phpの完成型
<!DOCTYPE html lang="ja">
<head>
<meta charset="UTF-8">
<title>テスト</title>
<script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<user-list
v-for="list in obj"
v-bind:key="list.id"
v-bind:list="list"
>
</user-list>
</div>
<script>
/* データ */
let obj =
[
{id:1, age:"26", name:"下北太郎"},
{id:2, age:"32", name:"大橋次郎"}
];
/* コンポーネント設定 */
let Component = {
props: ['list'],
template: `
<div>
<span>{{list.name}} {{list.age}}歳</span>
</div>
`
}
/* vue インスタンス作成 */
new Vue({
el:#app,
data:{ Obj },
components: {
'user-list': Component
}
})
</script>
</body>
</html>
解説