初心者がVue.jsの公式ガイドを勉強するメモ 算出プロパティとウォッチャ編


* 今回のお題はこちらです
* https://jp.vuejs.org/v2/guide/computed.html

## 基本例

*　index.html

``` html
<!DOCTYPE html>
<html>
<head>
  <title>Welcome to Vue</title>
  <script src="https://unpkg.com/vue"></script>
  <style>
    [v-cloak] { display:none; }
  </style>
</head>
<body>
  <div id="app">
    <div> {{ message }}</div>
    <div> {{ reverseMessage }}</div>
  </div>

  <script>

    var app = new Vue({
      el: '#app',
      data: {
        message: 'Hello !'
      },
      computed: {
        reverseMessage () {
          return this.message.split('').reverse().join('')
        }
      }
    })
    console.log(app.reverseMessage)
    app.message = 'Goodbye'
    console.log(app.reverseMessage)

  </script>
</body>
</html>
```

* App.vue

``` html
<template lang="pug">
  #app
    p Original message: "{{ message }}"
    p Computed message: " {{ reversedMessage }}"
    input(v-model="message")

</template>

<script>
import Vue from 'vue'


export default {
  name: 'app',
  data () {
    return {
      message: 'Hello Vue.js!',
    }
  },
  computed: {
    reversedMessage () {
      return this.message.split('').reverse().join('')
    }
  },
  methods: {
  }
}
</script>
```

* テンプレート内で、色々出来ますよということで、学んできましたが、基本テンプレート内であまりごちゃごちゃするなと言うことらしいです。
* 凹んだ気持ちを、リフレッシュしてcomputedの特徴を把握します。
* 特徴は、とりあえず、messageの値を常に監視していて、値が変わるまでは再描画処理は走らない。
* コンソールでも確認してみましたが、app.messageの値にリニアに反応しているのでOKです。
* 算出プロパティを使うときの注意点として、元の値を書き換えてしまう書き方をしないようにすることを念頭に置いて書く必要があります。

### 算出プロパティのキャッシュの確認
* 日付の更新で確認してます。

```html
<template lang="pug">
  #app
    p Methods: {{ dateMethod() }}
    p Computed: {{ dateComputed }}
    p Message : {{ message }}
    input(v-model="message")

</template>

<script>
import Vue from 'vue'

export default {
  name: 'app',
  data () {
    return {
      message: ''
    }
  },
  computed: {
    dateComputed () {
      return new Date().toLocaleString()
    }
  },
  methods: {
    dateMethod () {
      return new Date().toLocaleString()
    }
  }
}
</script>
```
* new Date()に変更していますが、意味合いは同じです。
* methodsは、DOMの更新時に一緒に更新されていますが、算出プロパティは買い換えられていなのが確認できます。
* この事からわかるように、computedが使える時は優先して使ったほうが良さそうです。


## 算出プロパティ vs メソッド

* App.vue

``` html
<template lang="pug">
  #app
    p Original message: "{{ message }}"
    p Computed message: " {{ reversedMessage }}"
    p Methods message: " {{ methodsMessage() }}"
    input(v-model="message")

</template>

<script>
import Vue from 'vue'


export default {
  name: 'app',
  data () {
    return {
      message: 'Hello Vue.js!',
      msg: 'msg'
    }
  },
  computed: {
    reversedMessage () {
      return this.message.split('').reverse().join('')
    }
  },
  methods: {
    methodsMessage () {
      return this.message.split('').reverse().join('')
    }
  }
}
</script>

```
* 復習になりますが methodsも、computedと挙動は変わらないです。
* 再描画(この場合、inputが入力)されると、methodsが実行されるにで、テンプレートに書いたmethodsがリニアに実行されます。 キャッシュの確認で確認しましたね
* computedもおなじですが、値が変わっていないと実行されない(キャッシュが実行されるだけ)。
* この場合もdataの値を変えないようにしないといけないです。
* ちなみにreturn で返さず、 this.messageに代入すると、意図しない結果になりますので、試してみるのもいいかもしれません。


## 算出プロパティ vs 監視プロパティ(watch)

* 監視プロパティ watch

* App.vue

``` html
<template lang="pug">
  #app
    div#demo {{ fullName }}
    button(@click="firstName='Tarou'") First Name
    button(@click="lastName='Momo'") Last Name

</template>

<script>
import Vue from 'vue'

export default {
  name: 'app',
  data () {
    return {
      firstName: 'Foo',
      lastName: 'Bar',
      fullName: 'Foo Bar'
    }
  },
  watch: {
    firstName (val) {
      this.fullName = `${val} ${this.lastName}`
    },
    lastName (val) {
      this.fullName = `${this.firstName} ${val}`
    }
  }
}
</script>
```

* 算出プロパティで書き換え

* App.vue

``` html
<template lang="pug">
  #app
    div#demo {{ fullName }}
    button(@click="firstName='Tarou'") First Name
    button(@click="lastName='Momo'") Last Name

</template>

<script>
import Vue from 'vue'

export default {
  name: 'app',
  data () {
    return {
      firstName: 'Foo',
      lastName: 'Bar',
      // fullName: 'Foo Bar'
    }
  },
  computed: {
    fullName () {
      return `${this.firstName} ${this.lastName}`
    }
  }
  /* watch: {
    firstName (val) {
      this.fullName = `${val} ${this.lastName}`
    },
    lastName (val) {
      this.fullName = `${this.firstName} ${val}`
    }
  } */
}
</script>
```

* こちらも、同じ事ができるならcomputedを使いましょうということでしょうか。
* watch は、data のインスタンス(dataの中)の値の書き換えを検知するものです。
  * firstNameの書き換えで発火して、それを元にfullNameを式で作ります。
  * lastNameも同じです この場合式は２つ必要です。
* computed はテンプレートにそのままfullNameを描画できますのでスマートでしょう first / last どちらかの値が変われば実行されます。
  * 式は、一つで済みます。 監視対象が多い場合computedの利が増加します。
* ちなみに、童話の桃太郎に苗字は無いそうです。

## 算出 Setter 関数

* App.vue

``` html
<template lang="pug">
  #app
    //- getter
    div#demo {{ fullName }}

    //- setter
    button(@click="fullName = 'John Doe'") John Doe button
    form(@submit.prevent="fullName = newItem")
      input(v-model="newItem" placeholder="John Doe")
      input(type="submit" value="Change Full Name")

</template>

<script>
import Vue from 'vue'

export default {
  name: 'app',
  data () {
    return {
      firstName: 'Foo',
      lastName: 'Bar',
      newItem: ''
    }
  },
  computed: {
    fullName: {
      get () {
        return this.firstName + ' ' + this.lastName
      },
      set (newValue) {
        const names = newValue.split(' ')
        this.firstName = names[0]
        this.lastName = names[1]
      }
    }
  }
}
</script>

```
* 算出プロパティは、指定しなければgetterになり、値はセット出来ないが設定をすれば、setterの役割も有効になり値をセットできるようになるとのこと。
* まぁ、単純な値セットじゃないから、それはそうですよね。
* テンプレートで無理やり使うとこんな感じでしょうか。

## ウォッチャ

* すいません、飛ばします(笑)

＊今回は、これで終了になります。　git commitして、終わります。