Vue.jsを更に学ぶ(2日目)

#条件付きレンダリングとリストレンダリング(v-if,v-show,v-for)

##v-elseが機能しないダメなコード

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
ダメなコード
<div id="app">
  <p v-if="ok">ok</p>
  <p>Hello</p>
  <p v-else>not ok</p>
</div>
```

```js
new Vue({
	el: '#app',
  data: {
  	ok: false
  }
})
```

このようにv-elseがv-ifの直後に来ていないと、条件分岐が機能しなくなるので注意が必要。

##複数のタグの表示を切り替えたい時

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
  <template v-if="ok">
    <p>hello</p>
    <p>おはよう</p>
    <p>こんばんは</p>
  </template>
  <button @click="ok = !ok">ボタン</button>
</div>
```

```js
new Vue({
	el: '#app',
  data: {
  	ok: false
  }
})
```

このように<template>で囲んであげて、そこにv-ifを付けてあげれば良い。
divタグだと検証したときにdivタグが存在するが、templateタグだと存在しない。

ちなみに、templateタグにv-showを指定しても機能しない。
なぜなら無くなるtemplateタグにdisplay: none;を指定しても意味がないから。

何度も切り替える場合はv-showを選ぶ。
v-showは初回の描画時にコストがかかるが、描画してしまえばあとはそこまでコストがかからない。


初期とほとんど変わらない場合はv-if。
v-ifはtrue,falseが切り替わる度に要素をドムから消すのでそこにコストがかかる。

##v-for復習

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

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

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

###index番号を取得する

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

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

###objectを渡す

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
  <ul>
    <li v-for="(value, key, index) in object">
      {{ index }}.{{ key }}:{{value}}
    </li>
  </ul>
</div>
```

```js
new Vue({
	el: '#app',
  data: {
    object: {
    	firstName: '太郎',
      lastName: '田中',
      age: 20
    }
  }
})
```

このように、

```
v-for="(value, key, index) in object
```

と指定することができる。

###v-forとtemplateタグを一緒に使う

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
  <template v-for="(value, key, index) in object">
    <li>
      {{ index }}.{{ key }}:{{value}}
    </li>
    <hr>
  </template>
</div>
```

```js
new Vue({
	el: '#app',
  data: {
    object: {
    	firstName: '太郎',
      lastName: '田中',
      age: 20
    }
  }
})
```

templateタグにv-forがついているので、毎回hrタグが適用される。そのため、要素ごとに線で区切って表示することができる。

###v-forで1~10まで表示する

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
  <ul>
    <li v-for="n in 10">{{n}}</li>
  </ul>
</div>
```
これだけで1~10まで表示することができる。


ちなみに、inはofに置き換えて書くことができる。

v-forを使う時はkey属性をお忘れなく。


#Vueインスタンスと内部構造

##複数のVueインスタンスを作る

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app1">
  {{ message }}
</div>

<div id="app2">
  {{ message }}
</div>
```

```js
new Vue({
	el: '#app1',
  data: {
    message: 'インスタンス１'
  }
})

new Vue({
  el: '#app2',
  data: {
  	message: 'インスタンス2'
  }
})
```

ただ、なるべく1つのVueインスタンスで書いた方が良い。

##外側からVueインスタンスにアクセス

結論から言うと、Vueインスタンスを変数に代入する

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app1">
  {{ message }}
</div>

<div id="app2">
  {{ message }}
  <button @click="changeMessage1">
    インスタンス１を変更
  </button>
</div>
```

```js
var vm1 = new Vue({
	el: '#app1',
  data: {
    message: 'インスタンス１'
  }
})

var vm2 = new Vue({
  el: '#app2',
  data: {
  	message: 'インスタンス2'
  },
  methods: {
  	changeMessage1: function() {
    	vm1.message = 'インスタンス2から変えました'
    }
  }
})
```

##リアクティブになるかならないか

```js
var vm = new Vue({
	el: '#app',
  data: {
    //リアクティブになる
    message: 'インスタンス１'
  }
})
//リアクティブにならない
vm.name = '太郎'
```


これは、Vueインスタンス内に書かれたプロパティはインスタンス作成時にgetterとsetterが設定されるから。

インスタンス外に書くと、それが設定されないからリアクティブにならない。


##dataオプションに変数dataを指定する

```js
var data = {
  message: 'インスタンス１'
}
//変数dataをdataオプションに指定している。
var vm = new Vue({
	el: '#app',
  data: data
})
```

このように指定することもできる。

##$dataの参照

```js
var data = {
  message: 'インスタンス１'
}
//変数dataをdataオプションに指定している。
var vm = new Vue({
	el: '#app',
  data: data,
  computed: {
  	myData: function() {
    	return this.$data
    }
  }
})

console.log(data === vm.$data)
```

このように、Vueインスタンス内ではthis.$dataで参照することができる。
外の場合は、vm.$dataで参照できる。

##$mountを使って後からマウント

```js
var data = {
  message: 'インスタンス１'
}
//変数dataをdataオプションに指定している。
var vm = new Vue({
	/* el: '#app', */
  data: data,
  computed: {
  	myData: function() {
    	return this.$data
    }
  }
})
//後からelオプションを使いたい
vm.$mount('#app')
```

直接$mountを使うこともできる。

```js
var vm = new Vue({
	/* el: '#app', */
  data: data,
  computed: {
  	myData: function() {
    	return this.$data
    }
  }
}).$mount('#app')
```

##templateプロパティを使ってみる

```js
var vm = new Vue({
  el: '#app',
  data: {
  	message: 'Hello'
  },
  computed: {
  	myData: function() {
    	return this.$data
    }
  },
  template: '<h1>テンプレートプロパティ</h1>'
})
```

templateプロパティは文字列内に直接タグを使って書く。
ただ、template:以下に書いた物しかviewには反映されないので、
htmlファイルに何か書いて、template:でも何か書いて、、ということはできない。

##render関数

```js
var vm = new Vue({
  el: '#app',
  data: {
  	message: 'Hello'
  },
  computed: {
  	myData: function() {
    	return this.$data
    }
  },
  //デフォルトで引数をとることができる。
  //引数名は何でもいいが、return以降のメソッド名と統一させること。
  //render関数では仮想ドムを返している。
  //一般的なcreateElementsメソッドは直接ドムを作成する
  render: function(createElement) {
  	return createElement('h1','こんにちは' + this.message);
  }
})
```

引数名、メソッド名は何でもok

```js
render: function(h) {
  	return h('h1','こんにちは' + this.message);
  }
```

これでもok


##仮想DOM

仮想DOMとはDOM要素を模したJSのオブジェクト。

仮想DOMが必要な理由は、

前提として、新しいDOMを作るのは非常にコストがかかる。

仮想DOMはJSのオブジェクトだから変更もすぐできる。

変更前の仮想DOMと変更された仮想DOMを比較して変わったところだけ実際のDOMで変更させることで効率的になるらしい。

.$mountなどは、仮想DOMを~~に適用させるよーって意味なのか。


##コンポーネント復習

```html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
  <hello></hello>
</div>
```

```js
Vue.component('hello', {
	template: '<p>こんにちは</p>'
})

var vm = new Vue({
  el: '#app'
})
```

注意点としては、コンポーネントは後ろにVueインスタンスを定義しないと使えない。