【Vue】Vue開発で使えるいくつかの小技

# Vueまとめパート4（小技集）
こちらの記事は、Adnan Babakan 氏によりDev.to上で公開された『 Vue advanced tricks cheat sheet 』の邦訳版です（原著者から許可を得た上での公開です）

- 元記事：[Vue advanced tricks cheat sheet](https://dev.to/adnanbabakan/vue-advanced-tricks-cheat-sheet-3ee3)

---

![Cover image for Vue advanced tricks cheat sheet](https://res.cloudinary.com/practicaldev/image/fetch/s--kydOtW61--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/i/q7z8ooekfx39ggpsv19m.png)

DEV.toコミュニティの皆さん、こんにちは！


普通にVueで開発をしていると、解決するべき多くの問題に遭遇しますが、開発者にとって長時間苛立たせる問題を解決することほど気持ちいいことはないなと感じています！

ここで、私はいくつかの問題を解決するために使用したいくつかの小技を書いています。これを読んでいるあなたにもいつか役立つかもしれません。


<!-- 
[](#table-of-content)Table of content
=====================================

*   [Force re-rendering](#force-re-rendering)
*   [Watching nested data](#watching-nested-data)
*   [Custom components with v-model support](#custom-components-with%20v-model-support)
*   [Functional component](#functional-component)

-->

## `vm.$forceUpdate()` -  強制的再レン​​ダリング

場合によっては仮想DOMの一部の変更を反映できないことがあるため、このような場合ではVueにコンポーネントを再レンダリングさせる必要がある。

このような場合には他にも`v-if`を使うなどいくつか方法があるが、`forceUpdate`メソッドを使うのが正しいとされている。

```javascript

export default {
  methods: {
    forceUpdateMyComponent() {
      this.$forceUpdate()
    },
  },
}
```    

Vueインスタンスでこのメソッドを使用するためには`$`をメソッド名の前につける必要があることに注意。

使ってみるとわかるがどの算出プロパティも更新されず、コンポーネントのビューが強制的に再レン​​ダリングされるだけだ。


## ネストされたデータの監視

場合によっては、ネストされたデータを監視したい場合もあるだろう。このような場合は`.`チェーンで実現できる。

```javascript

  export default {
	data() {
	  return {
		myInfo: {
		  firstName: 'Adnan'
		}
	  }
	},
        
        // `myInfo.firstName`とつなげることで監視プロパティにできる 
	watch: {
	  'myInfo.firstName'() {
		console.log('Here')
	  }
	}
  }
```    

上記のコードは、オブジェクト内の監視するプロパティどれかがわかっている場合に使える。

しかし、オブジェクト全体とその値を監視したい場合はどうすればいいか？
その場合は次のようにする。

```javascript

  export default {
    data() {
      return {
        myFruits: {apple: 'red', banana: 'yellow'}
      }
    },

    methods: {
      changeIt() {
        this.myFruits.apple = 'green'
      }
    },

    watch: {
      myFruits: {
        // `deep`, `handler`プロパティを追加する
        deep: true,
        handler() {
          console.log('Fruits updated!')
        }
      }
    }
  }
```    

監視プロパティを関数としてではなくオブジェクトとして定義し、`deep`キーとその値を`true`にセットする。これによってオブジェクト全体を監視でき、`handler`と呼ばれる関数内にデータが変更されたときに発生させたいことを書くことができる。

## v-modelをサポートするカスタム(子)コンポーネント

ご存じのとおり`v-model`はコンポーネント（input要素）とデータプロパティを介した双方向バインディングを実現するために使われる。

カスタム(子)コンポーネントを作成し、`v-model`をサポートさせたい場合は、`input`キーワードを発行し、最初にコンポーネントに渡されるものを`v-model`で受け取るために、`value`と呼ばれるpropを取得する必要がある。


より理解しやすくするために、次のコードを見てみよう。

```vue
<template>
    <div>
        <label>My custom test input: <input :value="inputValue" @input="emitTheData" /></label>
    </div>
</template>

<script>
  export default {
    props: ['value'],

    data() {
      return {
        inputValue: value
      }
    },

    methods: {
      emitTheData() {
        this.$emit('input', this.inputValue)
      }
    }
  }
</script>

``` 

この単純なコンポーネントは、渡されたデータを2つの方向にバインドする。

注：ご覧の通り、`value`というpropを`inputValue`というデータに割り当てて、それをinputタグで使用した。propをinput要素に直接渡すことができると思うかもしれないが、**Vue公式で言われている通り、propsは直接変更しない方がよい**。

## 関数型コンポーネント

監視プロパティまたは算出プロパティとメソッドのないコンポーネントがあると想像してみよう。それを使うだけで、`props`を使ってコンポーネントをレンダリングすることが可能だ。これが可能であれば、ライフサイクルメソッドもないため描画時間を短縮することができる。

それが関数型コンポーネントだ。

関数型コンポーネントは次のように定義できる。

```vue
<!-- `template`要素の中に`functional`含めると関数型コンポーネントになる -->
<template functional>
  <div>{{ props.foo }}</div>
</template>
``` 

このコンポーネントは関数型コンポーネントであるため、**`this`コンテキストは使えない**ことに注意。

Vueの関数型コンポーネントの詳細については、以下のリンクから確認できる。

- [関数型コンポーネント](https://jp.vuejs.org/v2/guide/render-function.html#%E9%96%A2%E6%95%B0%E5%9E%8B%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88)