Vue.jsについて学んだことまとめ

## 目次
1. Vue.jsとは
2. Vue.jsの基本

## 今回の学習のゴール
- Vue.jsとは何か、何ができるかを知る
- 実際の基本的な使い方について知る

## 1. Vue.jsとは
> Vue (発音は / v j u ː / 、 view と同様）はユーザーインターフェイスを構築するためのプログレッシブフレームワークです。他の一枚板(モノリシック: monolithic)なフレームワークとは異なり、Vue は少しずつ適用していけるように設計されています。
[Vue.js](https://jp.vuejs.org/v2/guide/)

- それぞれの意味
    - ユーザーインターフェイス（UI）: コンピュータとユーザーがそれぞれ情報をやり取りする際の入力や表示方法などの仕組み
        - ex. GUI, CUI
        - Vue.jsはUIを構造化し、UIを個別にコンポーネント化できるため、システム全体をコンポーネントの集合として開発できる
    - プログレッシブフレームワーク : Vue.js作者のEvan You氏が提唱する概念
        - サポートするツールやライブラリによって、どんな規模でもどの段階のアプリケーションでも柔軟に対応できる

- 特徴
    - View層にフォーカスしたJavaScriptライブラリ
        - View層 : レスポンスをクライアントにとって都合のいい画面に変換する層（実際のユーザーの目に見える領域）
    - 再利用可能な部品（コンポーネント）として様々な機能を実装できる
    - HTMLをベースとするテンプレート構文を利用することで様々な表示をHTMLの中に組み込むことができる
    - DOM要素とJavaScriptのデータを結びつけるリアクティブなデータバインディング
        - リアクティブなデータバインディングとは、HTMLテンプレート内で対象となるDOM要素にバインディングを指定することで、Vue.jsがそのデータの変更を検出する度に、バインディングされているDOM要素が自動で表示内容を更新すること
            - DOM : Document Object Modelの略称で、プログラムからHTMLを自由に操作するための仕組み 
            - リアクティブ : 再度アクティブになるという意味
                - データが更新されると自動的にそれらのデータを利用している画面の表示も自動的に更新されるので、データを操作するだけで表示を更新できる
            - バインディング : 複数の事柄どうしを結びつけたり対応づけたりすること
        - Vue.jsは基本的にJavaScriptのスクリプトを使って、HTMLのタグを操作するものと考えて良い

## 2. Vue.jsの基本

###  Vueの導入
- HTMLファイルの`<head>`タグ内に以下を記述

```html:html
// 開発バージョン
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

// 本番バージョン
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
```

### プロジェクトとしての開発
- プロジェクトの作成
    - プログラムの作成に必要なスクリプトファイルやイメージなどのファイル、各種のライブラリやフレームワークなどをまとめて管理するためのもの

```console
$ vue create vue-app    # vue-appというプロジェクトを作成
```
- プロジェクトを実行

```console
$ npm run serve    # localhostに「Welcome to Your Vue.js APP」というデフォルトのページが表示される
```
- プロジェクトの実行によって生成されたvue-appフォルダの中身はざっと以下の通り
    - フォルダ
        - .git : Gitというツールで使用するフォルダ
        - node_modules : npmで管理されるモジュール類がまとめられたフォルダ
        - public : HTMLやCSSなど公開されるファイル類が保管されたフォルダ
        - src : Vue.jsで作成したファイルなどがまとめられたフォルダ
    - ファイル
        - .eslintrc.js : ESLintで使うファイル
        - .gitignore : Gitというツールで使用するファイル
        - package.json : npmでパッケージ管理するための設定ファイル
        - postcss.config.js : PostCSSというツールの設定ファイル
        - READM .md


- 作成したプロジェクトをWebサーバーにアップして公開する

```console
$ npm run build    # distというフォルダが作成される
```
- ビルドによって生成されたdistフォルダの中身はざっと以下の通り
    - フォルダ
        - CSS 
        - js
        - img
    - ファイル
        - favicon.ico
        - index.html : デフォルトで表示されるHTMLファイル

### 宣言的レンダリング
- 単純なテンプレートにレンダリングする対象を宣言的に記載することでデータを変更するたびに、リアクティブなDOMレンダリングと、ユーザによる入力データの同期が可能である
    - レンダリング : 画面に表示すべき内容を、与えられたデータから計算しながら描き出すこと
    - 宣言的(Declarative) : 何がしたいのかという目的を宣言すること（処理の仕方はコンピュータに任せる）
        - 反対語である命令的（Imperative）は、どのようにしたいのかという方法を細かく指示すること

→ 要は、画面に表示したい内容を以下のようにテンプレートに当てはめるだけで、簡単に描画することができるってことが言いたいのだろう

```haml:html
<div id="app">    <!-- IDを使って操作の対象となるタグを指定する -->
  {{ message }}    <!-- mustache構文 HTMLの中に値を埋め込むためのもの -->
</div>
```
```javascript:js
var app = new Vue({    // Vueというオブジェクトを作成し変数appに代入
  // オプションを記載 使用するデータやメソッドを定義する
  el: '#app',    // アプリケーションを紐付ける要素(element) DOM要素を示すセレクタを指定する
  data: {    // アプリケーションで使用するデータ dataに用意された値が対象となるタグ内の{{}}に置き換えられる
    message: 'Hello Vue!'    // この値に応じて描画が更新される
  }
})
```
```:表示内容
Hello Vue!
```
### renderプロパティを用いたレンダリング
- renderは、Vueに用意されているレンダリングを行うためのプロパティ
    - 上記の例はHTMLに用意された{{}}に値をはめ込んでいるだけだが、renderを使用すると表示内容そのものを作成することができる
    - 以下の例では、renderが`<p>・・・・・data.message・・・・・</p>`のようなタグそのものを作成している

```html:html
<body>
  <h1>Vue.js</h1>
  <div id="app">
    {{ message }}
  </div>
  <hr>
  <button onclick="doAction();">    <!-- onclick属性でbutton要素がクリックされたかをイベントとして判断できる doAction()関数でアクションを実行-->
    click
  </button>
</body>
```
```javascript:js
var data = {
  message: 'Hello Vue!'
};

var app = new vue ({
  el: '#app',
  data: data,    // dataプロパティの値には変数dataを指定
  render: (element) => {    // renderプロパティで表示内容を作成 elで設定したタグの部分にレンダリングしたものをはめ込むことができる アロー関数の引数elementには関数が渡されている
    return element("p",    // returnで関数elementの実行結果を返す 引数には追加するタグ名とその属性、追加するタグに表示する値を指定
      {'style':'font-size:20pt; coler:red;'},    // 第2引数の属性は省略可
      data.message);
  }
})

function doAction() {                 // doAction()関数が呼び出されると
  data.message = "You Clicked!!!";    // 変数dataのmessageが上書きされる
}
```
```:ページをリロードしたときの表示内容
Hello Vue!
```
→ renderで組み込んだpタグの内容（=変数dataに用意したmessageのテキスト）が、`font-size`は20pt、`coler`はredで表示される

```:clickボタンを押下したときの表示内容
You Clicked!!!
```
→ リアクティブ機能が働いていることがわかる

###### ※ returnの戻り値は`VNode`というオブジェクト

- `VNode`は関数returnで生成されるもので、仮想DOMとして扱われるオブジェクトのこと
    - DOMとはData Object Modelの略で、HTMLなどの1つ1つの要素（タグ）をプログラミング言語で扱えるようにするために用意された仕組み
- JavaScriptではHTMLを読み込んだ段階で、各ダグの要素が作成され、それらの組み込み状態などがHTMLと全く同じ形で再現される（組み込まれて構造的に作られた構造をDOMツリーという）
- Vue.jsではDOMツリーが構築された後、それぞれの要素に対する仮想DOMの要素が作られ、仮想DOMのDOMツリーが作成される
- 仮想DOMの値が変更されれば、常にDOMの値も更新されるような対応がなされており、HTMLの表示タグも変更される
- DOMツリーは状態を常にチェックできないが（状態を常にチェックしたい場合はその処理を記述する必要がある）、仮想DOMは常に状態が管理され、変更があるたびに実際のDOMに変更内容が反映される
- 表示内容を複数のタグを組み合わせて表示させたい場合は、次のように子ノードを組み込む
` return 関数 ( タグ名, { 属性 }, [ VNode, VNode, ・・・・・] )`

```javascript:例
var app = new vue ({
  el: '#app',
  data: data,
  render: (element) => {
    return element("ol",    // <li>タグを<ol>タグの子ノードとして組み込む
    // element関数を使って<li>タグのVNodeのオブジェクトを作成 配列に値をまとめる
    [
      element("li", "item 1"),
      element("li", "item 2"),
      element("li", "item 3")
    ]);
  }
})
```
```:表示内容
1. item 1
2. item 2
3. item 3
```

### 要素の属性をバインディング
- タグのコンテンツとしてテキストを表示させる場合は{{}}記号を使用したが、タグの属性の値に変数などを設定したい場合はv-bind:を使う

```html:html
<h1>Vue.js</h1>
<div id="app">
  <p v-bind:style="style">{{ message }}</p>    <!-- v-bind:style属性にstyle変数の中身が設定される -->
</div>
<hr>
<input type="number" onChange="doChange(event);" value="20">    <!-- onChange属性の値に入力フォームの内容が変更された場合の処理を記述 -->
```
```javascript:js
var data = {
  message: 'Hello Vue!'
  style: 'font-size:20pt; color:red;'
};

var app = new vue ({
  el: '#app',
  data: data
});

function doCahnge(event) {
  data.style = 'font-size:' + event.target.value + 'pt; color:red;';    // event.target.valueでイベントが発生した対象（入力フォーム）の値を取り出す style属性の値が変更される
}
```
→ inputタグに入力されたnumberに合わせてfont-sizeが変更する

### 条件分岐とループ
- v-if ディレクティブは、条件に応じて描画したい場合に使用され、ディレクティブの式が真を返す場合のみ描画される

```html:html
<div id="app">
  <span v-if="seen">Now you see me</span>    <!-- 値には真偽値として扱える変数などの条件を記述 trueであれば表示内容が表示される-->
</div>
```
```javascript:js
var app = new Vue({
  el: '#app',
  data: {
    seen: true
  }
})
```
```:表示内容
Now you see me
```

- v-forディレクティブは、リストの項目を配列内のデータを使って表示させることができる

```html:html
<div id="app">
  <ol>
    <li v-for="todo in todos">    <!-- "変数 in 配列"と記述し、配列の値を順に取り出し変数に入れてダグを出力する -->
      {{ todo.text }}
    </li>
  </ol>
</div>
```
```javascript:js
var app = new Vue({
  el: '#app',
  data: {
    todos: [
      { text: 'Learn JavaScript' },
      { text: 'Learn Vue' },
      { text: 'Build something awesome' }
    ]
  }
})
```
```:表示内容
1. Learn JavaScript
2. Learn Vue
3. Build something awesome
```

### ユーザー入力の制御
- v-onディレクティブを使ってイベントリスナを加え、Vueインスタンスのメソッドを呼び出す
    - イベントリスナ : イベントに対して処理を結びつける仕組み

```html:html
<div id="app">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>    <!-- v-on:クリック名 = "処理（今回は関数の名前）"と記述する -->
</div>
```
```javascript:js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {    // v-onの値に記述した関数の名前はmethodsプロパティに用意する
    reverseMessage: function () { 
      this.message = this.message.split('').reverse().join('')
    }
  }
})
```
```:ボタンを押した時の表示内容
!sj.euV olleH
```
- v-modelディレクティブを使って入力とアプリケーションの状態の「双方向バインディング」を行う
    - inputタグに入力された値をVueのdataプロパティの値にバインドする機能である
    - リアルタイムにバインドされた変数の値が更新されるので、下記の例ではpタグで表示される内容とinputタグに入力されている内容がリアルタイムで同等の値になる


```html:html
<div id="app">
  <p>{{ message }}</p>
  <input v-model="message">    <!-- 変数messageにバインド -->
</div>
```
```javascript:js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})
```
### コンポーネントシステム
- 自己完結的で、再利用可能である小さい単位のコンポーネントを組み合わせることによって、大規模のアプリケーションを構築できる
    - 以下の例は変数をコンポーネントに渡す処理

```html:html
<h1>Vue.js</h1>
<div id="app">
  <hello/>    <!-- helloコンポーネントを使用 -->
</div>
```
```javascript:js
Vue.component('hello',    // helloコンポーネントを定義
{
  data:function() {    // コンポーネントのdataプロパティに変数の値を関数として用意する必要がある
    return {
      message: 'New message'    // 変数の情報
    };
  },
  template: '<p class="hello">{{message}}</p>',    // templateに設定した内容がコンポーネントとして表示される dataで設定したmessageの値が埋め込まれている
});

var app = new Vue({    // コンポーネント用のタグをレンダリングするためにVueオブジェクトの処理も行う
  el: '#app',
});
```




## 参照
- [Vue.js - ガイド](https://jp.vuejs.org/v2/guide/)
- 『[Vue.js入門 基礎から実践アプリケーション開発まで](https://gihyo.jp/book/2018/978-4-297-10091-9)』技術評論社