Vue.js テンプレート制御ディレクティブ まとめ

## はじめに

[Vue.jsでTO DOアプリを作る](https://qiita.com/yukiji/items/dc45f45f7f3f0e53f626)の続きです。

今回はディレクティブを深掘りしていきます。

## v-once

- 初回だけテキストバインディングを行う。
- 初回以降は静的なコンテンツとして扱う。
- 描画更新のパフォーマンスを上げたいときに利用できる

```js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    click(e) {
      // 文字列を反転するメソッドを定義
      this.message = this.message
        .split('')
        .reverse()
        .join('')
    }
  }
})
```

以下は`v-once`を定義しているので、初回だけテキストバインディングを行っている。

初回以降は静的なコンテンツとして扱われるので、ボタンをクリックしてもメソッドが発火しない。

```html
<p v-once> <!-- v-onceを定義 -->>
  {{ message }} <!-- Hello Vue.js -->
</p>
<button v-on:click="clickHandler">
    文字が反転
</button>
```

## v-pre

- 要素と全ての子要素のコンパイルをスキップする。
- 生のマスタッシュタグが表示される。

```html
<p v-pre>
  {{ message }} <!-- {{ message }} -->
</p>
```

## v-html

- プレーンなHTMLを挿入する。
- 指定した要素のinnerHTMLを更新できる。
- 主にサーバーサイドから取得したHTMLを表示したいときに使う。

`data`オプションのプロパティにHTMLをセットする。

```js
data: {
  messageHtml: 'Hello <span style="color:red;">Vue.js!</span>'
}
```

`v-html`ディレクティブで展開する。

```html
<p v-html="messageHtml"></p>
```

※XSS脆弱性を引き起こす恐れがあるため、サービスを利用するユーザーが入力したコンテンツには使用しないこと。

## v-cloak

ページを表示開始してから、インスタンスの作成が終わるまでにマスタッシュタグなどのコンパイル前にテンプレートが表示されてしまうのを防ぐ。



```html
<p v-cloak> <!-- v-cloakを定義 -->
  {{ message }}
</p>
```

`v-cloak`に対して`display: none`を設定する。

```css
[v-cloak] {
  display: none;
}
```

## v-text

`data`オプションのプロパティをマスタッシュ構文以外で表示したい時。

使い道あんまりなさそう。

```html
<p v-text="message"></p> <!-- Hello Vue.js! -->
```

## JavaScript式

データバインディング内部では`JavaScript式`を利用する事ができる。

```js
data: {
  message: 'Hello Vue.js!',
  number: 100,
  ok: true
}
```

```html
<p>
  {{ number +  1}} <!-- 101 -->
  {{ message.split('').reverse().join('') }} <!-- !sj.euV olleH -->
</p>
```

フロー制御は`三行演算子`を利用する。

```html
<p>
  {{ ok? 'YES' : 'NO' }} <!-- YES -->
</p>
```

以下は式では無く文なのでエラーになる。

```html

<p>
  {{ var x = 1 }} <!-- error -->
</p>
```

## フィルタ(ローカル)

Vue.jsでは式の終わりにフィルタを追加することができる。

```js
data: {
  price: 29800 //dataオプションにプロパティを設定
},
filters: { // filterにメソッドを追加
  numberFormat(value) {
    return value.toLocaleString()
}
```

`{{ 式 | フィルタ }}`でfilterを実行する

```html
<p>
  {{ price | numberFormat(price) }} <!-- 29,800 -->
</p>
```

`v-bind`ディレクティブで使用する場合

```html
<input type="text" v-bind:value="price | numberFormat(price)">
```

## フィルタ(グローバル)

フィルタはグローバルにも定義できる。

グローバルに定義するには`Vueインスタンス`を生成するよりも前に記述する。

```js
// グルーバルフィルタを定義
Vue.filter('numberFormat', function(value) {
  return value.toLocaleString()
})

// Vueインスタンス生成
var app = new Vue({
  el: '#app',
  data: {
    price: 29800
  }
})
```

## フィルタの連結

フィルタは複数連結できる。

フィルタで加工した返り値に対して、さらにフィルタをかけることができる。

```html
<p>
  {{ A | filterX(A) | filterY(A) }}
</p>
```

## フィルタの引数

フィルタで引数を利用する。

例として、長いテキストを省略して`...`を末尾に付与するフィルタを作成する。

その際、`表示する文字列`と`末尾に付与する文字`を引数で指定できるようにする。

`data`オプションに長い文字列を持った`text`プロパティを用意する。

```js
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
```

続いてフィルタを定義する。

JavaScriptのメソッド`substring`は第一引数が開始位置、第二引数が抽出する文字数を指定する。

以下のフィルタは、引数で`文字列`、`抽出する文字数`、`連結する文字`を受け取る。

```js
Vue.filter('readMore', function(text, length, suffix) {
  return text.substring(0, length) + suffix
})
```

実行してみる。

```html
<p>
  <!-- textは引数に含まないことに注意 -->
  {{ text | readMore(10, '...') }} <!-- Lorem ipsu... -->
</p>
```

```html
<p>
  {{ text | readMore(5, '***') }} <!-- Lorem*** -->
</p>
```

## v-bind省略記法

`v-bind`は省略記法が存在する。

プロジェクト内で統一するのが望ましい。

以下は同じ結果が出力される。

```html
<!-- 完全な構文 -->
<a v-bind:href="url">

<!--  省略記法-->
<a :href="url">
```

## 更新履歴

:zap:[Vue.jsの基本的な使い方まとめ](https://qiita.com/yukiji/items/862b8dd91dc410259fb4)
:zap:[Vue.jsでTO DOアプリを作る](https://qiita.com/yukiji/items/dc45f45f7f3f0e53f626)
:zap:[Vue.js テンプレート制御ディレクティブ まとめ](https://qiita.com/yukiji/items/a77dd6d8dd0f194770c3) :point_left:今ココ
:zap:[Vue.js 算出プロパティとメソッドの違い](https://qiita.com/yukiji/items/525469503cdba334658e)