【写真とコード付き】Vue.jsで書くHTMLのコントロールの方法【４選】

<br>

## はじめに
この記事は**Vue.jsの基本は抑えられている程**で、話を進めていきます。もしVue.jsを初めて触ると言う方は、こちらの記事を参照していただければと思います。

⬇️**【写真とコード付き】Vue.jsの構築から基本的な書き方まで1から解説【超初心者向け】**
https://qiita.com/yuki4839/items/62f40564e3f4c8dbfc51
<br>

さて今回は、主に**テンプレート(HTML)をコントロールするため**のディレクティブについて、5つほどご紹介させていただこうと思います。

早速いきましょう。
<br>
<br>

## 実行環境
使用ツール、デバイスはこちら

<ul>
  <li>Google chrome</li>
  <li>Mac OS Catalina</li>
  <li>Visual Studio Code</li>
</ul>
<br>

また今回使用するディレクトリ階層はこちら。

```html:ディレクトリ階層
─ root(任意のディレクトリ)
│
├─ index.html
│
├─ css
│   └ style.css
│
└─ js
    └ main.js
```
<br>

各ファイルの初期値はこちら。

```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <link rel="stylesheet" href="./css/style.css">
</head>

<body>

  <div id="web">
    <p>
      {{ context }}
    </p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
  <script src="./js/main.js"></script>
</body>

</html>
```

```css:style.css
/* 出力結果を見やすくするためのスタイルです */
body {
  background-color: #add8e6;
}

#web {
  background-color: #fff;
  margin: 20px;
  padding: 20px;
  width: 300px;
}
```

```js:main.js
const web = new Vue({
  el: '#web',
  data: {
    context: `Hello Vue.js!`
  }
})
```
<br>

現時点での出力結果はこちら。

![スクリーンショット 2020-12-12 21.13.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882660/fb3335b5-8937-d54c-f34d-0c96d64eaff6.png)
<br>
<br>

### v-once
まず最初は、**初期描画時のみ動的な動き**をさせたい時に利用する、`v-once` ディレクティブについてです。

実際のコードはこちら。

```html:index.html
<!-- headタグ省略 -->
<body>

  <div id="web">
    <p v-once>
      {{ counter }}
    </p>
    <button v-on:click="counter++">
      Click!
    </button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
  <script src="./js/main.js"></script>

</body>
```

```js:main.js
var web = new Vue({
  el: '#web',
  data: {
    counter: 0
  }
})
```

ポイントは、描画時のみ動的な動作をさせたいタグに、`v-once` ディレクティブを記述してやる点です。

これにより上記の場合、本来であればクリックすると、counter変数がクリック数分だけカウントされていくのですが、`v-once` ディレクティブによりその動作はなくなります。

主に初期描画後の**描画コストを抑えたい時**になどに利用します。
<br>
<br>

### v-pre
次は、マスタッシュ構文などで囲まれている表記を、**エスケープ処理して表示**させる事ができる、`v-pre` ディレクティブについてです。

実際のコードはこちら。

```html:index.html
<!-- headタグ省略 -->
<body>

  <div id="app">
    <p v-pre>
      {{ message }}
    </p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
  <script src="./js/main.js"></script>

</body>
```

```js:main.js
var web = new Vue({
  el: '#web',
  data: {
    message: 'Hello Vue.js!'
  },
})
```

ポイントは、エスケープ処理を行いたいタグに、`v-pre` ディレクティブを記述する事です。

これにより上記の場合、通常は `Vueインスタンス` で定義された、messageの値である「Hello Vue.js!」が描画されますが、`v-pre` タグによってエスケープされているため、マスタッシュ構文がそのまま描画されるようになります。
<br>

念のため出力結果はこちら。

![スクリーンショット 2020-12-14 22.37.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882660/b5a82a65-4dd6-9312-3a18-9bd09174ebd2.png)

<br>
<br>

### v-html
次は `Vueインスタンス` で定義された値に、もし `HTML` としての記述があった場合、それを読み込んで出力させる `v-html` ディレクティブについてです。

実際のコードはこちら。

```html:index.html
<!-- headタグ省略 -->
<body>

  <div id="web">
    <p v-html="message"></p>
    <p>
      {{ message }}
    </p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
  <script src="./js/main.js"></script>

</body>
```

```js:main.js
var web = new Vue({
  el: '#web',
  data: {
    message: 'Hello <span style="color:red;">Vue.js!</span>'
  },
})
```

ポイントは、`v-html` の属性値に `Vueインスタンス` で `HTML` を含む形式で定義されているものを、読み込む事です。

これにより、通常のマスタッシュ構文では `HTML` がエスケープされた状態で出てくるのですが、`v-html` ディレクティブが付けられたタグでは、`HTML` がしっかり解釈されて出力される事になります。
<br>

出力結果はこちら。

![スクリーンショット 2020-12-14 22.46.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882660/e22d4f90-35d0-d1ca-5cb7-ed0719186209.png)

>因みにこちらのディレクティブをformなどで入力された値に使用すると、XSSなどの脆弱性を引き起こす可能性があるので、信頼できるソースのみの使用が推奨になります。

<br>
<br>

### v-cloak
最後は、`Vue.js` を利用していると、初期描画時にコンパイル前のテンプレート(HTML)が表示されてしまう事を防ぐ、`v-cloak` ディレクティブについてです。

`v-cloak` ディレクティブとは、初期描画がされている時は有効になり、逆に初期描画が終了すると、無効になると言う特徴があります。

この特徴を利用して、`v-cloak` ディレクティブに `display: none;` のスタイルを当ててやると、当該のタグ内の描画が初期描画(コンパイル)が終わるまで、表示されないようにする事ができます。**(いわゆるチラツキ防止)**
<br>

実際のコードはこちら。

```html:index.html
<!-- headタグ省略 -->
<body>

  <div id="web">
    <p v-cloak>
      {{ message }}
    </p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
  <script src="./js/main.js"></script>

</body>
```

```css:style.css
/* bodyと#webは省略 */
[v-cloak] {
  display: none;
}
```

```js:main.js
var web = new Vue({
  el: '#web',
  data: {
    message: 'Hello Vue.js!'
  },
})
```

ポイントは、マスタッシュ構文などのコンパイルされて表示されるタグに、`v-cloak` ディレクティブを追記し、`CSS` の方で上記のような記述を行います。

これで初期描画時のコンパイル前のチラツキ(上記であれば、マスタッシュ構文が一瞬そのまま表示されてしまう現象)を防止する事ができます。

<br>
<br>

## まとめ
以上が主にテンプレート(HTML)を操作するための、ディレクティブの一覧になります。もう一度まとめておくと以下の通りになります。

<ul>
  <li>v-once
    <ul>
      <li>初期描画時のみ動的にさせる</li>
    </ul>
  </li>
  <li>v-pre
    <ul>
      <li>エスケープ処理を施す</li>
    </ul>
  </li>
  <li>v-html
    <ul>
      <li>HTMLを解釈して表示する</li>
    </ul>
  </li>
  <li>v-cloak
    <ul>
      <li>チラツキ防止</li>
    </ul>
  </li>
</ul>

ぜひ実際にコードを書いて見てください！
最後まで読んでいただき、ありがとうございました！
<br>
<br>
<br>

筆者：yuki｜IT業界のリアルな転職事情など発信｜元トップ営業マン(訪販)→未経験からエンジニア転職へ
Qiita：https://qiita.com/yuki4839
Twitter：https://twitter.com/yukifullstack
<br>