Vue.js入門 2章 Vue.jsの入門（テンプレート、フィルタ、算出プロパティ）


前 [Vue.js入門 2章 Vue.jsの入門（コンストラクタ、マウント、data）](https://qiita.com/tseno/items/2ca326280603d2536c11)
次 [Vue.js入門 2章 Vue.jsの入門（ディレクティブ）](https://qiita.com/tseno/items/ccb0b99edbc2c1d136dc)

## テンプレート構文

- テンプレートでは、Vueインスタンスのデータビュー（DOMツリー）の関係を宣言的に定義する。データが決まればビューの内容が決定される。データが変更されれば自動的にビューも変更される。この変更の仕組みをデータバインディングという。
- Mustache記法によるデータの展開
    - `{{}}`の中に、データや式を記述する。
- ディレクティブによるHTML要素の拡張
    - `v-`で始まる属性。

### テキストへの展開

- `{{ }}`に囲まれた中で、dataプロパティに定義したデータや、算出プロパティ、メソッド、フィルタを参照できる。

```html
<p>{{ items[0].name }}: {{ items[0].price }} x {{ items[0].quantity }}</p>
```

### 属性値の展開

- `v-bind:属性名="データを展開した属性値"`で使う。

```html
<script src="https://unpkg.com/vue@2.5.17"></script>
<button id="b-button" v-bind:title="loggedInButton">購入</button>
<script>
  var vm = new Vue({
  	el: '#b-button',
    data: {
    	loggedInButton: 'ログイン済みのため購入できます。'
    }
  })
</script>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/8f00ba75-caf3-1dc2-8ef8-f49e14ffa3c1.png)

- v-bindに渡された属性値が真の場合、DOMにdisabled属性が追加される。
- v-bindに渡された属性値が偽の場合、disabled属性が削除される。(適切に処理される）

```html
<script src="https://unpkg.com/vue@2.5.17"></script>
<button id="b-button" v-bind:disabled="!canBuy">購入</button>
<script>
  var vm = new Vue({
  	el: '#b-button',
    data: {
    	canBuy: false
    }
  })
</script>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/3efdda85-4970-8814-52d7-466a09d106b5.png)

### JavaScript式の展開

- 単純なデータだけではなく、JavaScript式もサポートしている。JavaScript式は1つしか書けない。

```html
<p>{{ items[0].price * items[0].quantity }}</p>
```

## フィルタ（filters）

- フィルタとは、テキストフォーマット処理をする仕組み。（日付を`YYYY/mm/dd`に変換や、0.5を`50%`するなど）
- フィルタが使えるのは、Mustache展開とv-bindディレクティブの属性値の式のみ。

```js
// フィルタの定義
filters: {
  フィルタ名: function (value) {
    // return ...
  }
}

// フィルタの使用
{{ 値 | フィルタ名 }}
```
- テンプレートと、フィルタを使うサンプル

```html
<script src="https://unpkg.com/vue@2.5.17"></script>
<div id="app">
　<p>{{ items[0].name }}: {{ items[0].price }} x {{ items[0].quantity }}</p>
  <p>フィルター処理例 {{1000 | numberWithDelimiter}}</p>
</div>
<script src="app.js"></script>
```

```js
var items = [
  {
    name: '鉛筆',
    price: 300,
    quantity: 0
  },
  {
    name: 'ノート',
    price: 400,
    quantity: 0
  },
  {
    name: '消しゴム',
    price: 500,
    quantity: 0
  }
]
var vm = new Vue({
  el: '#app',
  data: {
    items: items
  },
  filters: { // この節で追加したフィルタの定義
    numberWithDelimiter: function (value) {
      if (!value) {
        return '0'
      }
      // 数値を3桁ずつカンマ区切りで返す
      return value.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1,')
    }
  }
})
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/3164b0be-cac6-3702-285f-79f6e96d1996.png)

## 算出プロパティ（computed）

- テンプレートに複雑な式をなるべく書かずに、算出プロパティのほうに書いて、その結果をテンプレートに出力する。

```js
new Vue({

  computed: { // 関数として実装、参照時はプロパティとして機能
    算出プロパティ名: function () {
      // return ...
    }
  }
})
```

### サンプルアプリケーションでの実装

- 算出プロパティの結果をフィルタで出力する。

```html
<script src="https://unpkg.com/vue@2.5.17"></script>
<div id="app">
  <p>{{ items[0].name }}: {{ items[0].price }} x {{ items[0].quantity }}</p>
  <p>小計: {{ totalPrice | numberWithDelimiter }}円</p>
  <p>合計(税込): {{ totalPriceWithTax | numberWithDelimiter }}円</p>
</div>
```

- 算出プロパティの実装
- 算出プロパティの中で、データや算出プロパティを参照したいときは、`this.items`、`this.totalPrice`ののように、`this`を付けて呼び出す。

```js
var items = [
  {
    name: '鉛筆',
    price: 300,
    quantity: 0
  },
  {
    name: 'ノート',
    price: 400,
    quantity: 0
  },
  {
    name: '消しゴム',
    price: 500,
    quantity: 0
  }
]
var vm = new Vue({
  el: '#app',
  data: {
    items: items
  },
  filters: {
    numberWithDelimiter: function (value) {
      if (!value) {
        return '0'
      }
      return value.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1,')
    }
  },
  computed: { // 算出プロパティ
    totalPrice: function () {
      return this.items.reduce(function (sum, item) {
        return sum + (item.price * item.quantity)
      }, 0)
    },
    totalPriceWithTax: function () {
      // 算出プロパティに依存した算出プロパティも定義できる
      return Math.floor(this.totalPrice * 1.08)
    }
  }
})
window.vm = vm
```

- コンソールで個数を3に変更した結果。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/88686/fb408ce5-7040-18a1-cd62-a89603cc66a6.png)

### まとめ
- テンプレート構文は、展開したいテキスト値を{{}}の中に記述する。Javascript式も書ける。v-bind:属性名で属性値の展開ができる。
- フィルタは、データをあるフォーマットに加工する機能。
- 算出プロパティは、データの計算や共通化に便利な機能。


参考
[Vue.js入門 基礎から実践アプリケーション開発まで](https://www.amazon.co.jp/dp/B07J6FP6NQ/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)