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

#Vue CLIでプロジェクトを開始する

npmとvueがインストールされている必要がある。

```
$ vue create アプリ名

$ cd アプリ名

$ npm run serve
```

これでrailsでいうところのyoure on rails　の画面がブラウザで表示できるようになる。


#ファイルの種類

babel.config.jsはES6をES5にトランスファイルするための設定を書くファイル。
ES6は古いブラウザは対応してないので、トランスファイルする必要があるらしい。

package.jsonはアプリの説明書的な物。バージョンなどが書いてある。
scripts以下はnmpコマンドの種類が載っている。
ex)npm serve 　 npm build 　npm lintなど。

package-lock.jsonはpackage.jsonと依存関係にある。

publicフォルダには静的なファイルを置いておく。
webpackはsrcフォルダ内のファイルに適用される。
ミニファイ化されたくないファイルなどをpublicフォルダに配置するが、ほとんど使わないらしい。

assetsフォルダは基本的にはRailsと変わらなそう。

componentsフォルダは、コンポーネントを置いておくフォルダ。

main.jsはindex.htmlに適用される。
最終的にはsrcフォルダ内のファイルがmain.jsに集約されてindex.htmlに適用させるってこと？
で、集約させるのがwebpackの役割。


##main.jsファイルを見てみよう。

```main.js
import Vue from 'vue'
import App from './App.vue'
//本番用のTipsを消すことができる
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
```


render関数は

```js
render: h => h(App)

render: function(h) {
  return h(App)
```

上と下は同じ意味になる。


今までは

```js
render: h => h('div', 'こんにちは')
```

こんな感じで書いていた。

今回は第一引数に謎のAppが入っているが。。。

render関数はオブジェクトを引数に指定することもできる。
今回はコンポーネントオブジェクトを引数に指定している。

##App.vueとは何か？

シングルファイルコンポーネントだよ。
improtするとコンポーネントオブジェクトになるもの。
これに関しては次項で説明する。

###Vue.jsで扱う単一ファイルコンポーネント
これは1つのファイルを1つのコンポーネントとして扱うこともので、コンポーネントとして描画されるHTMLや、そのコンポーネントで行う処理をまとめたjavascript、コンポーネントのデザインを調整するためのCSS、これら3つが一つのファイルにまとめられたものになります。


#デプロイ時の本番環境用のbuild

```
npm run build
```

このコマンドで本番用のbuildを行うことができる。


#コンポーネント

そもそもVueインスタンスは複数の要素に適用させることはできない。

```html
このように書いても、Vueインスタンスが適用されるのは上の1つ目だけ。
<div class="app">

</div>
<div class="app">

</div>
```
だから何か使いまわしたいものがあったらコンポーネント化する。

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

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

```js
Vue.component('hello', {
	data: function() {
  	return{
    	number: 12
    }
  },
  template: '<p>いいね({{number}})</p>'
})

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

何でコンポーネントはdataオプションを関数で指定する必要があるのか？

それは、オブジェクトで返してしまうと、1つの値が変わると全てのコンポーネントの値も変わってしまうから。
ちなみにコンポーネントのdata:で関数を使って返さないとエラーが起きる。

つまり、コンポーネントは別々のdata:を持つってこと？

##コンポーネントをローカル登録

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

<div id="app">
  <my-component></my-component>
</div>
```

```js
var component = {
  data: function() {
  	return{
    	number: 12
    }
  },
  template: '<p>いいね({{number}})</p>'
}

var vm = new Vue({
  el: '#app',
  components: {
  	'my-component': component
  }
})
```

##単一ファイルコンポーネントをグローバル登録してみる

```LikeNumber.vue
<template>
  <p>いいね({{number}})</p>
</template>
<script>
  export default {
    data() {
      return {
        number: 5
      }
    }
  }
</script>
```

```main.js
import Vue from 'vue'
import App from './App.vue'
import LikeNumber from "./LikeNumber.vue"

Vue.config.productionTip = false
Vue.component('LikeNumber', LikeNumber)

new Vue({
  render: h => h(App),
}).$mount('#app')
```

```App.vue
<template>
  <LikeNumber></LikeNumber>
</template>
```

順番は、単一ファイルコンポーネントを書く。

importでLikeNumberをコンポーネントオブジェクトとして参照できるようにして、

Vue.component('任意の名前', LikeNumber)とすることでグローバル登録。

これでどこでも<LikeNumber></LikeNumber>とすることで、コンポーネントを呼び出すことができる。

##template内のルート要素

注意点として、単一ファイルコンポーネントで、templateタグ内にコードを書く時は必ず一つの要素にしないといけない。

```LikeNumber.vue
これはダメ。
<template>
  <p>いいね({{number}})</p>
  <button>click</button>
</template>
```

```LikeNumber.vue
これならdivタグにまとめられているので、一つの要素とみなされる。
<template>
  <div>
    <p>いいね({{number}})</p>
    <button>click</button>
  </div>
</template>
```

##ローカル登録でコンポーネントを使う

```LikeHeader.vue
<template>
  <h1>いいね</h1>
</template>
```

```App.vue
<template>
  <div>
    <LikeHeader></LikeHeader>
    <LikeNumber></LikeNumber>
  </div> 
</template>

<script>
import LikeHeader from "./LikeHeader.vue"

export default {
  components: {
    'LikeHeader': LikeHeader
  }
}
</script>
```

まずはコンポーネントファイルを作る。

次に、App.vue内でimportを使ってLikeHeaderコンポーネントを使えるようにする。

最後に、ローカル登録するために、scriptタグ内に任意の名前で登録すれば、

<LikeHeader></LikeHeader>とすることで、LikeHeader.vueに書いた内容を呼び出すことができる。

実際はコンポーネントファイルはcomponentsフォルダ内にまとめることが多い。


##ケバブケースとパスカルケース

コンポーネント名をパスカルケースで設定すると、ケバブケースで書いてもコンポーネントを呼び出すことができる。

```.vue
パスカル(ケバブケースで呼び出し可能)
LikeHeader:LikeHeader

ケバブ(パスカルケースで呼び出し不可)
'like-header':LikeHeader

キャメルケース(ケバブケースで呼び出し可能、ただコンポーネントは基本的にはパスカルケースで統一しよう)
likeHeader: LikeHeader
```

htmlは基本的にケバブケースで書くので、パスカルケースにしておけば一眼でコンポーネントだと認識できる。

##スコープ付きcss


```LikeNumber.vue
<template>
  <div>
   <p>いいね({{number}})</p>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        number: 5
      }
    }
  }
</script>

<style scoped>
  div {
    border: 1px solid red;
  }
</style>
```

styleにscopedとすることで、そのコンポーネントにのみcssを適用することができる。

scopeはその範囲のhtmlタグに同じ属性を付与することで行っているらしい。