初めてのVue②v-bind,v-on,v-show,v-forの使い方

初めてのVue②v-bind,v-on,v-show,v-forの使い方

前の記事でVueの設定ができたら、Vueの便利機能を使ってみましょう。今回はv-bind,v-on,v-show,v-forを使っていきます。

この記事の対象者
  • Vueって何が便利なの?
  • Vueがどんなものか興味がある
  • とりあえずコードを見てみたい

まずはv-bindとv-onのサンプルコードから紹介します。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Document</title>
  <script src="https://unpkg.com/vue@3"></script>
  <style>
    .text-green{
      color:green;
    }
    .text-red{
      color:red;
    }
  </style>

</head>
<body>
 <div id="app2">
//ポイント①v-bindによってclassをリアクティブに操作できるようにしています。
      さらに、v-onによってクリックしたらtoggleが起動するように設定してあります
    <button v-bind:class="active ? 'text-red' : 'text-green'" v-on:click="toggle">Click me</button>
  </div>
 <script>
    Vue.createApp({
      data(){
        return{
          active: false
        };
      },

      methods:{
        toggle(){
          this.active = ! this.active;
        }
      }
    }).mount('#app2');
 </script>
</body>
</html>

これをブラウザで見てみるとこうなります。

ボタンをクリックするたびに赤と緑に変化したら成功です。

classに三項演算子(ifを一行で使うコード)をつけています。

今回はactiveが正ならtext-red、誤ならtext-greenが採用される仕組みになっています。

v-bind:class="active ? 'text-red' : 'text-green'" 

dataでactiveの初期設定をfalseにして、クリックするたびにture,falseを切り替えます。

簡単ですよね。

ちなみに

v-bindとv-onは下記のように省略する事ができます。

省略前
v-bind:class="active ? 'text-red' : 'text-green'" 
省略後
:class="active ? 'text-red' : 'text-green'" 

省略前
v-on:click="toggle"
省略後
@click="toggle"

v-bindではモデルの変更はできないと書きましたが、v-onと組み合わせることで変更できる場合もあります。

ただし、v-modelを使った方が早いです。

v-show,v-forの使い方

続いてv-show,v-forの使い方を紹介します。

まずはコードです。ちょっと長いですがこれからしばらく使うので頑張ってついてきてください。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Document</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>
<body>
 <div id="app3">
//ポイント①v-showによってassingments配列の中からcompleteがfalseのものを抽出して1つ以上(true)あれば表示されるようにしています
    <section v-show="assingments.filter(a => ! a.complete).length">
      <h2>In Progress Assingments</h2>
      <ul>
//ポイント②v-forによってassingments配列の中から一つずつ要素を取り出して表示しています。
      keyをv-bindしているのも隠れたポイントです。
        <li v-for="assingment in assingments.filter(a => ! a.complete)":key="assingment.id">
          <label>
            {{assingment.name}}
//ポイント③チェックボックスにv-modelを使うことでcompleteのture、falseを切り替えれるようにしています。
            <input type="checkbox" v-model="assingment.complete">
          </label>
        </li>
      </ul>
    </section>
//こっちはassingments配列の中からcompleteがtrueのものを抽出したバージョンです
    <section v-show="assingments.filter(a => a.complete).length">
      <h2>Completed</h2>
      <ul>
        <li v-for="assingment in assingments.filter(a => a.complete)":key="assingment.id">
          <label>
            {{assingment.name}}
            <input type="checkbox" v-model="assingment.complete">
          </label>
        </li>
      </ul>
    </section>
  </div>
 <script>
    let app3 = {
      data(){
        return{
          assingments: [
          {name: 'task1', complete: false, id: 1 },
          {name: 'task2', complete: false, id: 2 },
          {name: 'task3', complete: false, id: 3 },
          ]
        }
      }
    };

    Vue.createApp(app3).mount('#app3');

 </script>
</body>
</html>

ブラウザで確認してみます。

task1のチェックボックスをクリックして下記のようになれば成功です。

ポイントはコードの中に書いた通りです。

v-showはBoolean型のデータを受け取っています。

ちなみに、v-showとほとんど同じ使い方でv-ifというのもありますが、あまり違いがわからないです。

v-forはlaravelと同じような感じで使われていてコードの重複を大きく省いてくれます。

ちなみに、:key=”assingment.id”を使っているのはチェックボックスをクリックしたときに一つ下のチェックボックスにもチェックが入ってしまうのを防ぐためです。

説明しづらいのでこの設定の有無で試してみてください。

コードのシンプル化

今回紹介したコードが煩雑なためもう少しシンプルに書いてみます。

<div id="app3">
    <!-- <section v-show="assingments.filter(a => ! a.complete).length"> -->
    <section v-show="inProgressAssingments.length">
      <h2>In Progress Assingments</h2>
      <ul>
        <!-- <li v-for="assingment in assingments.filter(a => ! a.complete)":key="assingment.id"> -->
        <li v-for="assingment in inProgressAssingments":key="assingment.id">
          <label>
            {{assingment.name}}
            <input type="checkbox" v-model="assingment.complete">
          </label>
        </li>
      </ul>
    </section>

    <!-- <section v-show="assingments.filter(a => a.complete).length"> -->
    <section v-show="completeAssingments.length">
      <h2>Completed</h2>
      <ul>
        <!-- <li v-for="assingment in assingments.filter(a => a.complete)":key="assingment.id"> -->
        <li v-for="assingment in completeAssingments":key="assingment.id">
          <label>
            {{assingment.name}}
            <input type="checkbox" v-model="assingment.complete">
          </label>
        </li>
      </ul>
    </section>
  </div>
 <script>
    let app3 = {
      data(){
        return{
          assingments: [
          {name: 'task1', complete: false, id: 1 },
          {name: 'task2', complete: false, id: 2 },
          {name: 'task3', complete: false, id: 3 },
          ]
        }
      },

      computed: {
        inProgressAssingments(){
          return this.assingments.filter(assingment => ! assingment.complete);
        },

        completeAssingments(){
          return this.assingments.filter(assingment => assingment.complete);
        }
      }
    };

    Vue.createApp(app3).mount('#app3');

フィルターをかけるコードが重複してたので改善しました。

ポイントは下記のコードです。

computed: {
        inProgressAssingments(){
          return this.assingments.filter(assingment => ! assingment.complete);
        },
      }

computedはリアクティブにデータを処理したい時に使います。

クリックした時にだけしか処理したくない、という場合はmethodを使います。

computedで設定することでコードが改善されました。

改善前:v-show="assingments.filter(a => ! a.complete).length"
改善後:v-show="inProgressAssingments.length"

改善前:<li v-for="assingment in assingments.filter(a => ! a.complete)":key="assingment.id">
改善後:<li v-for="assingment in inProgressAssingments":key="assingment.id">

規模が大きくなるにつれてこうした配慮が大事になります。

関連記事