作成日: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にするのがポイントです。
*2)JSONの名称はJavaScript Object Notationの頭文字を取ってます。
データの集まり(Object)を扱うための表記法(Notation)となり、書き方のルールとして{"キー" : 値}となってるものをJSON形式と呼びます。
今回は動的なサイトをつくるというより、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>
データベースから取得したデータを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>
その① データベースからデータの取得
取得したデータをJSON形式に変換
$json_data = json_encode( $stmt, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
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テンプレート構文の{{ }}でデータを出力しているのが特徴的ですね。 属性タグは見やすいように改行していますが、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の設定部分です。

オプション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>
実際の表示

新規登録、移動時の座標登録のロジックはそのままですので、 見た目も機能も全く同じものになります。
#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>
<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>
props: にプロパティを登録します。 template: で記述したコンポーネントが、HTMLに挿入されます。
Vue()関数の中に、あらたにcomponents: プロパティを追加します。
components: {'コンポーネント名' : コンポーネント変数} とし、コンポーネント表示部分にコンポーネントデータを渡します。
このようにコンポーネントを用いても表示されることが確認できます。
コンポーネントを理解する
試しに以下のような画面表示になるものを作ってみたとします。 表示
 表示   htmlコード
index3.phpの完成型
 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>
解説

コーディングを図解するとこのようになります。
コンポーネントやデータを準備をしたのちに、vueインスタンスに登録します。
 

★別の書き方
コンポーネントの登録方法をグローバルにしたときの記述のしかた。
インスタンスにcomponentsを記述しない。特に理由がなければこちらではなく、ローカル設定でコンポーネントを作るほうが良いです。
 入門
入門 基礎
基礎 応用
応用 実践フロントエンド
実践フロントエンド 実践バックエンド
実践バックエンド デザイン
デザイン キッズ
キッズ