Vue

##なぜVueが必要？(React)

https://speakerdeck.com/dena_tech/techcon2021-17?slide=44

#Vue
https://jp.vuejs.org/index.html

**Progressive JavaScript Framework**
段階的に導入していける

##Version

3.0




##設計基盤
GUIライブラリに適した **MVVM**

-**M**odel
モデル
-**V**iew
表示(HTMLテンプレート)
-**V**iew **M**odel
表示するデータ及びデータを操作する手続きをひとまとめ

上記を管理するコントローラ(Controller)は、
存在するが隠蔽されているため、
コードを書く際に意識する必要はない

View ModelとViewのデータの連携をDirective（属性)で行い、
Viewを構成するパーツ(UIコンテナ)をComponent（部品)として切り出すことで、Viewの再利用のための部品化を可能に。

##関連ライブラリ,フレームワーク

```
##Routing
     Vue Router
##SSR/SSG
     Nuxt.js
##Data Management
     Vuex
##Internalization
     vue-i18n
```

##Vue Router
https://router.vuejs.org/ja/

Vue.jsを利用したSPA構築で、ルーティング制御をするための公式プラグイン(ライブラリ)

###UseCase
ページ遷移が多発するようなWebアプリ
例えば管理者画面やユーザページが存在するようなもの
URLをシェアするようなWebアプリ

##Vuex   
https://vuex.vuejs.org/ja/guide/

Vue.js アプリケーションのための 状態管理パターン + ライブラリです。 これは予測可能な方法によってのみ状態の変異を行うというルールを保証し、アプリケーション内の全てのコンポーネントのための集中型のストアとして機能する。

###UseCase
コンポーネントの階層が２階層以上になっており、祖父と孫の間で頻繁にイベントが発生するようなことが多い場合
複数のコンポーネントが同じ状態を参照して、複雑化しているようなケース



##UIframework
###Vuetify
https://vuetifyjs.com/ja/
###Bootstrap

###TailwindCSS


##Vue導入
3種類の方法
1.CDN
2.npm
3.CLI


#Vue CLI(Commnad Line Interface)
https://cli.vuejs.org/

コマンドラインを使ってvue.jsで開発を行うための前準備を支援してくれるツール

##導入

#VueCLIのファイル構成
```:ファイル構成
.git/  # バージョン管理システムGitのディレクトリ
node_modules/  # npm install コマンドでインストールしたnpmパッケージを管理するディレクトリ
public/  # webpackに処理されないアセットを格納するディレクトリ
 ├ favicon.ico  # ファビコン
 └ index.html  # index.htmlテンプレート
src/
 ├ assets/  # webpackに処理されるアセットを格納するディレクトリ
 ├ components/  # UIコンポーネント(単一ファイルコンポーネント)
 ├ views/ # webpackに処理されるアセットを格納するディレクトリ
 ├ App.vue  # 実行エントリポイントとなるコンポーネント
 ├ main.js  # アプリケーションのエントリポイントのスクリプトファイル
 └ router.js  # Vue Routerのルーティングファイル
.gitignore  # Git の管理に含めないファイルを指定するためのファイル
babel.config.js  # Babelの設定ファイル
package.json  # npmのモジュール、タスク定義
package-lock.json  # 依存パッケージが依存するパッケージのバージョン情報が変わる場合、package.jsonだけではnode_modulesを別環境で再現できなくなる。それを解決するためのファイル。基本、さわることはない。むずかしい(´*ω*｀)
README.md # プロジェクトのREADMEドキュメント。npmコマンドの一覧が書かれている
vue.config.js
```
##node_modules/
npmコマンドでインストールしたライブラリの情報がすべて保存
npmコマンドでライブラリを追加するとこの中に格納される。



##public/
webpackによって処理されないアセットを格納。

public/のリソースはwebpackによる処理はされず、dist/にコピー、配置される。
例えば、public/に「/public/img/img01.png」というリソースがあった場合、それは、そのままの状態でdist/コピー、配置(/dist/img/img01.png)されます。

###index.html
SPAの起点になるファイル。このファイルを元に、バンドリングされるJSファイルのURLがscript要素のsrc属性に自動的に挿入されます。さらに、このファイルとバンドリングされたJSファイルやアセットがdist/(ビルド時に作成される)に配置。

vue.jsを利用する場合`<div id=”app”>`に指定しているidをVueインスタンスの作成時に指定することでid=”app”以下の要素をすべてvue.jsの制御下に置くことが可能。vue.jsの制御下に置かれた要素は、vue.jsを使って操作を行うことができる。



##src/
主にwebpackに処理されるアセットを格納。
中にassets/、components/、views/、App.vue/、main.js、router.jsが格納。

```srcディレクトリの構成について

src/
 ├ assets/  # webpackに処理されるアセットを格納するディレクトリ
 ├ components/  # UIコンポーネント(単一ファイルコンポーネント)
 ├ views/ # webpackに処理されるアセットを格納するディレクトリ
 ├ App.vue  # 実行エントリポイントとなるコンポーネント
 ├ main.js  # アプリケーションのエントリポイントのスクリプトファイル
 └ router.js  # Vue Routerのルーティングファイル
```

##assets/
webpackによる処理を加えるファイルを格納。

##components/
.vueファイル(単一ファイルコンポーネント)を格納。
アプリケーション内で何度も使うようなパーツはコンポーネント化しておくと便利。

##views/
ページデータを格納。拡張子は「.vue」

##App.vue
viewsディレクトリに格納したページはApp.vueを通して表示する。
アプリケーション全体で使うナビゲーションはここで設定。

##main.js
Vueの基本設定ファイル。
App.vueをhtmlに紐付けます。
ルーティングを行うVue Routerや状態管理を行うVuexなどの機能を追加する場合はmain.jsファイルの中にそれらの機能を利用するために必要となるコードを追加する

###router.js
VueリソースのURLやURLに紐づくコンポーネント等を設定。
通常のWebアプリケーションと違い、SPAにページ内リンクを設置する場合はrouter.jsを編集する必要があります。

##基礎
# 環境
[JSFiddle](https://jsfiddle.net/)でVueを選択するだけでVue.jsを試し打ちできる環境が作れます。
![スクリーンショット 2019-08-25 22.38.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/1d799b95-3331-a376-03b4-eb74b5be3687.png)

# 基本構文
## Vueインスタンスの生成
new VueでVueインスタンスを生成し、その中のel要素で、html側のどの部分を対象としてVueを使用するか定義することができます。

```html:html
<div id='app'>
</div>
```

```js:js
new Vue({
  el: '#app'
})
```

## 変数
### data
Vueインスタンス内のdata要素に変数を定義することができます。格納した変数はhtml側で`{{ }}`をつけると呼び出し可能

```html:html
<div id='app'>
  <p>{{ message }}</p>
</div>
```

```js:js
new Vue({
  el: '#app',
  data: {
    message: 'Hello VueJS!'
  }
})
```

<img width="307" alt="スクリーンショット 2019-08-25 17.34.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/a143ebf2-daa0-a5e1-d234-4f4148fd3675.png">


### computed
関数の戻り値を変数として利用する場合はVueインスタンス内のcomputed要素に定義

```html:html
<div id='app'>
  <p>{{ datetime }}</p>
</div>
```

```js:js
new Vue({
  el: '#app',
  computed: {
    datetime: function(){
      return new Date();
    }
  }
})
```

<img width="437" alt="スクリーンショット 2019-08-25 17.36.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/607dae6a-bcc8-54a3-ab9f-08f03d3c2372.png">


## 関数
Vueインスタンス内のmethods要素に関数を定義することができます。html側に関数名を記載することで呼び出し可能（`@click`については後述）

```html:html
<div id='app'>
  <p>{{ message }}</p>
  <button @click='reverse'>反転</button>
</div>
```

```js:js
new Vue({
  el: '#app',
  data: {
    message: 'Hello VueJS!'
  },
  methods: {
    reverse: function(){
      this.message = this.message.split('').reverse().join('');
    }
  }
})
```

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/5934c41b-c220-a5d7-51da-34a14d086ca4.gif)

# ディレクティブ
htmlタグの中に定義できるVue.js独自の属性のこと
## v-bind
タグ属性の値をVueインスタンス内で定義した変数で表現する際に使用

```html:html
<div id='app'>
  <a v-bind:href='url'>Qiita</a>
</div>
```

```js:js
new Vue({
  el: '#app',
  data: {
    url: 'https://qiita.com'
  }
})
```

![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/38757f35-7ebe-8110-3cf7-beb4ad47a38c.gif)


`v-bind:`を`:`に省略可

```html:html
<div id='app'>
  <a :href='url'>Qiita</a>
</div>
```

## v-on
イベントのトリガーと呼び出す関数を定義する際に使用

```html:html
<div id='app'>
  <p>{{ message }}</p>
  <button v-on:click='reverse'>反転</button>
</div>
```

```js:js
new Vue({
  el: '#app',
  data: {
    message: 'Hello VueJS!'
  },
  methods: {
    reverse: function(){
      this.message = this.message.split('').reverse().join('');
    }
  }
})
```

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/5934c41b-c220-a5d7-51da-34a14d086ca4.gif)

`v-on:`を`@`に省略可

```html:html
<div id='app'>
  <p>{{ message }}</p>
  <button @click='reverse'>反転</button>
</div>
```

## v-model
双方向バインディング（「入力フォーム⇆Vue変数」の同期）を実現する際に使用

```html:html
<div id='app'>
  <input type='text' v-model='message'>
  <p>{{ message }}</p>
</div>
```

```js:js
new Vue({
  el: '#app',
  data: {
    message: 'Hello VueJS!'
  }
})
```

![ezgif.com-video-to-gif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/f8479e2d-ad28-6793-bcc6-54cb42fe6d57.gif)


## v-if
条件に応じて表示させるhtml要素を動的に変更する際に使用

```html:html
<div id="app">
  <button @click="countUp">ボタン</button>
  <p>{{ count }}</p>
  <p v-if="isMultipleOf4">4の倍数</p>
  <p v-else-if="isMultipleOf2">偶数</p>
  <p v-else>奇数</p>
</div>
```

```js:js
new Vue({
  el: "#app",
  data: {
    count: 0
  },
  computed: {
    isMultipleOf4: function(){
      return this.count%4==0;
    },
    isMultipleOf2: function(){
      return this.count%2==0;
    }
  },
  methods: {
    countUp: function(){
      this.count += 1;
    }
  }
})
```

![ezgif.com-video-to-gif (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/bb029a62-6fd5-9ea8-1935-2cfac39b1f04.gif)


## v-for
配列やオブジェクトの中身を反復表示させる際に使用

```html:html
<div id="app">
  <ul>
    <li v-for="fruit in fruits">{{ fruit }}</li>
  </ul>
</div>
```

```js:js
new Vue({
  el: "#app",
  data: {
    fruits: ['りんご','バナナ','ぶどう']
  }
})
```

<img width="69" alt="スクリーンショット 2019-08-25 19.21.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/e068af24-fb1b-e29e-ed10-fff8f3b093ab.png">

# コンポーネント
コンポーネントとは再利用可能なVueインスタンス要素
複数のコンポーネントを作成して、それを部品のように組み立てることで1つのWebページを作成可能

## js側の書き方
コンポーネントの要素をオブジェクトで書きます（`component`変数の部分）。
書き方はVueインスタンス内での定義方法とほぼ同一です。
※data部のみ、Vueインスタンスが生成されるときの初期変数を関数で返してあげるようにします。

Vueインスタンスでコンポーネントを利用可能にする二通りの書き方。
1.`Vue.component([コンポーネント名],[コンポーネント要素])`で全てのVueインスタンスで有効にする方法。
2.Vueインスタンス内のcomponents部に記載することで、特定のVueインスタンスで有効にする方法

```js:js
var component = {
　data: function(){
　　　return {
　　　　　count: 0
　　　}
  },
  template: "<p>{{count}}<button @click='increment'>+1</button></p>",
  methods: {
  	increment: function(){
    	this.count += 1;
    }
  }
}

//方法１
Vue.component("sample-component",component)
new Vue({
  el: "#app",
})

//方法２
new Vue({
  el: "#app",
  components: {
  	"sample-component": component
  }
})
```

## html側での書き方
html内で先ほど指定したコンポーネント名でタグを書くだけで、その部分が丸っとコンポーネントに置きかわります。

```html:html
<div id="app">
  <sample-component></sample-component>
</div>
```

![ezgif.com-video-to-gif (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/5960fd7b-5e8d-0cdc-76a8-8c088f499375.gif)

再利用可能なので、このように複数配置可能

```html:html
<div id="app">
  <sample-component></sample-component>
  <hr>
  <sample-component></sample-component>
  <hr>
  <sample-component></sample-component>
</div>
```

<img width="143" alt="スクリーンショット 2019-08-30 9.43.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214279/b66ea9a2-7f06-7dd7-4249-70683e6dc650.png">



#用語

##SFC(Single File Component)


##

##

##

##

##