見出し画像

【Vue.js】ディレクティブと使い方をおさらい

ライフマップ開発チームの石上です。
前回の記事で、Vue.jsの超・初歩的な内容を確認しました。しかし、あれだけではとても実務で使用することはできません。より実用的な機能を実装する上で必要となるものが、「ディレクティブ」です。

Vue.jsには特有の属性が複数用意されており、それらを「ディレクティブ」と呼びます。「v-」という接頭辞を持っていることが特徴で、それらを利用することでHTML要素に動的な振る舞いを追加することができます。
Vue.jsの恩恵を受けるためには必須となる知識です。

今回の記事では、Vue.jsにおける主要なディレクティブを紹介していきたいと思います。


v-bind

v-bindは、HTML要素の属性の値を設定します。例えば、class属性やsrc属性、href属性などの値を、Vue側で定義したものに設定することができます。

記述する際は「v-bind:〇〇」という書き方が基本形式となります。〇〇の部分には、classやsrcなど、任意の属性を入れてください。

<div id="app">
  <p v-bind:class="color">クラス属性の値にredが代入されます。</p>
  <img v-bind:src="src" >
  <a v-bind:href="url">href属性の値にhttps://www.google.com/が代入されます。</a>
</div>
const app = Vue.createApp({
  data: () => ({
    color: 'red',
    src: 'assets/img/text.jpg',
    url: 'https://www.google.com/',
  })
})
app.mount('#app');

値にマスタッシュ構文({{ ... }})を使用するのは不適切です。よくある間違いなので、注意してください…!

<!-- 正しいv-bindの使い方ではありません -->
<p class="{{ color }}"></p>

真偽値でクラスを付け外し

v-bindを利用することで、真偽値の値に応じてクラスをつけ外しすることができます。

<div id="app">
  <p v-bind:class="{ active: isActive }">isActiveの値がtrueの場合、クラスが付与されます</p>
</div>
const app = Vue.createApp({
  data: () => ({
    isActive: true,
  })
})
app.mount('#app');

このように書くと、「isActiveの値がtrueの場合、activeというクラスを付与する」という設定にできます。

三項演算子でクラスを切り替え

クラスのつけ外しだけでなく、切り替えも可能です。以下のように三項演算子を用いるで、「真偽値がtrueの場合はactive、falseの場合はinactive」という切り替えができるようになります。

<div id="app">
  <p v-bind:class="{ isActive ? active : inactive }">isActiveの値がtrueの場合はactive、falseの場合はinactiveというクラスが付与されます</p>
</div>

v-bindの省略記法

さて、長々とみてきましたが、このv-bindは省略して記述することもできます。と言っても大したものではありません。

<!-- 通常の書き方 -->
<p v-bind:class="color">クラス属性の値にredが代入されます。</p>

<!-- 省略した書き方 -->
<p :class="color">クラス属性の値にredが代入されます。</p>

「:」とだけ書くことでv-bindを利用することが可能です。
コードが簡潔になるため、一般的には省略記法が使用されることが多いですが、初学者(自分も含め)は最初は完全な形式で書くことをお勧めします。

v-model

v-modelはフォームの入力要素(input、select、textarea)に設定可能で、入力された内容を値として保持することができます。

例えば以下のように記載すると、userTextの値とテキストボックスに入力した内容が同期され、リアルタイムで更新されます。

<div id="app">
  <input type="text" v-model="userText">
  <p>{{ userText }}</p>
</div>
const app = Vue.createApp({
  data: () => ({
    userText: ''
  })
})
app.mount('#app');

つまり…

  • テキストボックスの内容が変更されたら、その値をVueインスタンスのデータとして更新する

  • 逆にVueインスタンスのデータに変更があった場合も、テキストボックスの内容が更新される

…という仕組みですね。
これがVue.jsの特徴の一つである、双方向データバインディングです。

v-for

Vueインスタンスで定義した配列、オブジェクトを繰り返し出力することができます。ざっくり言うとループ処理ですね。
基本的な記述形式は以下のようになります。

v-for="要素名 in 配列(もしくはオブジェクト)"

配列を出力

例えば、「配列colorsに格納された色を片っ端から出力させたい」という場合には、以下のように書きます。

<div id="app">
  <ul>
    <li v-for="color in colors" v-bind:key="color.name">
     {{ color.name }}
    </li>
  </ul>
</div>
const app = Vue.createApp({
  data: () => ({
    colors: [
      {name: 'red'},
      {name: 'green'},
      {name: 'blue'},
    ]
  })
})
app.mount('#app');

また、第二引数にindexを設定できます。

<div id="app">
  <ul>
    <li v-for="(color,index) in colors" v-bind:key="color.name">
      {{ index }} _ {{ color.name }}
    </li>
  </ul>
</div>

オブジェクトを出力

オブジェクトにも利用可能です。

<div id="app">
  <ul>
    <li v-for="user in users" v-bind:key="user.name">
      {{ user.name }}_{{ user.age }}_{{ user.from }}
    </li>
  </ul>
</div>
const app = Vue.createApp({
  data: () => ({
    users: [
      {
        name: 'oshiro',
        age: '33',
        from: 'okinawa'
      },
      {
        name: 'ishigami',
        age: '27',
        from: 'tokyo'
      }
    ]
  })
})
app.mount('#app');

v-forには必ずkey属性をつけるべし!

見出しの通りですが、v-forディレクティブを使用する際には必ずkey属性を併用しましょう。

key属性とは、v-forで描画される各アイテムに識別子(キー)を提供するために必要となります。これにより、要素の再描画や再利用が最適化されます。

記述自体は非常にシンプルで、サンプルコードに書かれている通り、v-bind:key="〇〇"と書けばOKです。(key属性用のIDなどを設定しておくのが安全な運用方法でしょうか)

<div id="app">
  <ul>
    <li v-for="user in users" v-bind:key="user.id">
      {{ user.name }}_{{ user.age }}_{{ user.from }}
    </li>
  </ul>
</div>

指定しない場合、Vue.jsはリスト内のアイテムを一意に識別できなくなります。アイテムの状態を正確に保持できなかったり、意図しない挙動(アイテムの順序が変更されたときに正確に反映されない等)が発生したり、不具合が起こる可能性が出てきます。
具体的な事例を紹介してくださっている記事がありますので、よければぜひそちらもご参照ください。

【Vue.js】v-forを使う時の注意点 key属性をつけ忘れないようにする
https://note.com/shift_tech/n/nbcae6c4ab442

https://note.com/shift_tech

v-if / v-show

要素の表示非表示を制御したい場合、v-if もしくは v-showを使います。どちらも真偽値によって制御可能で、trueであれば要素は表示され、falseであれば表示しません。

<!-- 要素の表示非表示を制御 -->
<div id="app">
  <p v-if="isDisplay">isDisplayがtrueなら表示、falseなら非表示</p>
  <p v-show="isDisplay">isDisplayがtrueなら表示、falseなら非表示</p>
</div>
const app = Vue.createApp({
  data: () => ({
    isDisplay: true,
  })
})
app.mount('#app');

v-ifとv-showの違い

どちらも要素の表示/非表示を制御するディレクティブですが、その動作には異なる点があります。

  • v-if:true の場合は対象要素 DOM に挿入し、false の場合は破棄。
    切り替えが発生する度に DOM の作成と削除が行われるため、レンダリングにコストがかかる。

  • v-show:いかなる場合でも対象要素は常にDOMに残り、表示非表示はCSSのdisplayプロパティでのみ制御。

これらを踏まえて、切り替えの頻度に応じて以下のように使い分けると良いでしょう。

  • 切り替えの頻度が低い:v-if

  • 切り替えの頻度が高い:v-show

v-else / v-else-if

条件付きのレンダリングを行う際に、v-ifとセットで使います。

v-else

直前のv-ifがfalseの場合に実行されます。

<div id="app">
  <div v-if="condition">
    <!-- 条件が true の場合のコンテンツ -->
  </div>
  <div v-else>
    <!-- 条件が false の場合のコンテンツ -->
  </div>
</div>

v-else-if

直前のv-if がfalseで、なおかつ自身の条件が true の場合に実行されます。v-else-if は連続して使え、条件が一致する最初のブロックが表示されます。

<div id="app">
  <div v-if="condition1">
    <!-- 条件1true の場合のコンテンツ -->
  </div>
  <div v-else-if="condition2">
    <!-- 条件1false でかつ条件2true の場合のコンテンツ -->
  </div>
  <div v-else>
    <!-- 条件1と条件2false の場合のコンテンツ -->
  </div>
</div>

v-on

要素にイベントリスナーを設定するために使用されます。
例えば、「ボタンがクリックされたときに handleClick というメソッドを呼び出す」という仕組みを実装する際には、以下のように記述します。

<div id="app">
  <button v-on:click="handleClick">クリック</button>
</div>
const app = Vue.createApp({
  methods: {
    handleClick() {
      console.log('テスト');
    }
  }
})
app.mount('#app');

v-onの省略記法

v-bindと同様に、v-onにも省略記法が存在します。こちらも非常にシンプルで、v-onを@に置き換えるだけです。
上のサンプルコードを省略記法で書くと以下のようになります。

<div id="app">
  <button @click="handleClick">クリック</button>
</div>

終わりに

今回の記事では、Vue.jsの主要なディレクティブについてご紹介しました。これらを使いこなすことでより実用的な機能を実装できるようになります。また、今回紹介したもの以外にもディレクティブは多数存在しますので、ぜひ使いこなせるよう一緒に頑張りましょう。

次回の記事では、今までの知識を踏まえてちょっとした機能(モーダル、タブなどなど…)を実装したいと考えています。

ではまた次回!石上でした〜


この記事が気に入ったらサポートをしてみませんか?