（３）VueによるReactiveプログラミング　その１

Vueを使って簡単なプログラムを作成して、特にリアクティブなUIの基本的な動作を確認してみたいと思います。

#参考ドキュメント

- [Vueドキュメント](https://jp.vuejs.org/index.html)
- [Vuetifyガイド](https://vuetifyjs.com/en/)

#リアクティブプログラミング

今までのリアクティブではないプログラミングでは、例えば、テキストの入力を受け付けて、その入力文字列を表示するには、何らかのイベント（ボタンの押下）をきっかけに、入力値の変数への格納と画面の表示を同時に変更する、というものでした。
これに対し、リアクティブなプログラミングでは、データとUIが密接に繋がっていて、プログラムの変数の値が変更されたら、画面にはその値が自動的にに表示される、というような動きをします。そのため、開発者は、プログラムで保持している値だけに注意してプログラミングすればよく、コードの量も少なくなることが期待できます。

#Vue+Vuetifyのプロジェクトを作成

```> vue create react01```
```> cd react01```
```> vue add vuetify```

全て、Defaultを選択してプロジェクトを作成します。

src/components/HelloWorld.vue　を使ってVueの動作を確認しようと思います。
最初に、HeeloWorld.vueの必要な物（```<template> <v-container> <script>```）だけを残して、あとは全部削除してしまいます。削除すると、下のようになります。

![vscode_helloworld1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/90e5c7aa-6e0a-1df6-ce5f-2d5def020016.png)


これで、Terminalから、

```> npm run serve```

でローカルのサーバを起動し、さらに、デバッガーからブラウザを起動すると、App.vueにある、上部のバー（```<v-app-bar>```)だけが残った状態になるはずです。

![hello.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/68bf58ba-6af6-fbf1-0bf4-78ba472d52b9.png)

ここで、HelloWorld.vueファイルの、```<template>...</template>```の部分は、主に画面のUIをHTMLベースで記述した部分になり、```<script>...</script>```は、処理をJavaScriptで記述する部分になっています。
全体の動きを少し説明すると、Vueのアプリケーションがブラウザに読み込まれると、まず、main.jsが動作し、その中でApp.vueが読み込まれ、次にApp.vueにある```<template>```中の、```<HelloWorld/>```で、HelloWorld.vueが呼び出される、というように動いています。

#inputフィールドの作成
次は、Vuetifyにある、[テキストフィールド](https://vuetifyjs.com/en/components/text-fields/)```<v-text-field>```を使って、入力した内容が画面にリアルタイムに表示されるプログラムを上記の画面に追加しようと思います。

HelloWorld.vueを以下のように変更します。Visual Studio CodeのTerminalで実行しているローカルサーバはそのまま実行したままで構いません。

```vue
<template>
  <v-container>
      {{ message }}
    <v-text-field v-model="message" />
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: function () {
    return {
      message: ''
    }
  }
};
</script>
```

変更したファイルを保存すると、自動的に再コンパイルされ、ブラウザ情は、以下のような画面になります。

![hello-react.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/10ea9721-d24b-d1d9-004f-b6401cbe25ce.png)

ラインが表示されている入力のフィールドに文字を入力すると、それにしたがって、上部に同じ文字が表示されるのがわかると思います。

ここで、```<v-text-field>```のタグの中にある、```v-model```とあるプロパティで指定されているのが、リアクティブに反応する変数です。この変数を、```<script>```の```data```の部分に記述することで、この```message```という変数が、Vueで管理されるようになります。
さらに、```{{message}}```を```<template>```の```<v-container>```の中に記述すると、その変数の中身を表示することができるようになります。

#テキストフィールドをかっこよくする

テキストフィールドは、様々なプロパティを設定することで、簡単にプロダクトレベルのUIに仕上げることができます。
```<v-text-field>```を以下のようにして確認します。

```vue
    <v-text-field 
      label="Input your message here."
      prepend-icon="mdi-message-text-outline"
      v-model="message" />
```

そうすると、テキストフィールドの前にアイコンが表示され、また、テキストフィールドにlabelに設定した文字が表示されます。入力を始めると小さなフォントでテキストフィールドの上部に表示されるのがわかるかと思います。

![vuetify-input.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/5149e796-0261-893b-165a-cb36d8e2d8ce.png)

アイコンは、マテリアルデザインの[アイコンのリスト](https://materialdesignicons.com/)から、検索して選ぶことができます。表示されるアイコンの名前の前に、```mdi-```をつけて、```prepend-icon```に設定するだけです。

#おまけ１ nameは必要？
"HelloWorld.vue"の中で指定されているnameは、必ずしも必要ありません。nameは、Vueが必要なコンポーネントを探すときのキーになりますが、.vueファイルに記述されている場合は、自動的にファイル名がnameに設定されるためです。

#おまけ2 リアクティブな動作はどうやって実装されているのか
変数に格納されているデータが変更されると、どのような仕組みを使って関連する変数が変更されたり、処理が動いたりできるのでしょうか。
それについては、[Vueのガイド](https://jp.vuejs.org/v2/guide/reactivity.html)や、[この記事](https://qiita.com/ryo511/items/b3e639be256d17e31422)が参考になると思います。

簡単に説明すると、ES5から追加された、Object.defineProperty を使って、変数の読み出しをフックして、変数の値が変更された時に実行すべき処理の依存関係を登録し、いざ変更されたときにそれらの処理を実行する、ということを行っています。

#おまけ3 アロー関数
JavaScriptのfunctionの書き方は、ES6からアロー関数```=>```で記述することができるようになっています。単純に全体として短くなりますし、returnを省略できたり、条件によってかっこや波括弧を省略できたりするので、すっきり書くことができます。ただ、functionで宣言された関数と、アロー関数の中とでは、```this```の参照の仕様が変わっているので注意が必要です。thisの参照については、[こちらの記事](https://qiita.com/soarflat/items/b251caf9cb59b72beb9b)や[こちらの記事](https://qiita.com/mejileben/items/69e5facdb60781927929)が参考になると思います。

参考までに、functionキーワードを使って書くと

```vue
export default {
  name: "HelloWorld",
  data: function () {
    return {
      message: ''
    }
  }
};
```

ですが、アロー関数を使って以下のように書くこともできます。

```vue
export default {
  name: "HelloWorld",
  data: () => ({
    message: ''
  })
};
```