Vue CLI のHello Worldって難しくないですか。(Vue.js初心者)

# はじめに
Vue.jsなるものを触ってみようと思って、インストールしてみました。
んで、ネットで調べてみると、どうにもVue CLIなるのもが便利らしく、みんなそれを使って環境をぱっと作って、云々みたいな記事が多いわけです。
そこで私もEnter連打してVue CLIの環境を作ったのですが、、、

**初心者には何もわからん…**
.Vueって何…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244678/a65debc7-e6c8-5564-bc92-a4d964103427.png)
(Vue公式 https://jp.vuejs.org/v2/guide/installation.html より)

なるほど、玄人向けなんだな。でもガイド参照しろって書いてあるしガイド見たら理解できるだろ。と思って、ひとまずガイドの最初の方を読みましたが、まだわからない…

**結局ほぼ全部ガイド読みました**

正直なところ、HelloWorld理解するのにガイド全部読むことになるとは思ってなかったので、学習コストが低いとは何なのか…になってしまいました。しかも全部読む間に内容結構忘れちゃうし。

これでも学習コストは低いほうなのかもしれませんが、自分みたいにとりあえず触ってから学んで行きたいタイプにはなかなか厳しかったです。なので、今回Hellow Worldを理解するのに最低限必要なことをちょっとまとめようと思います。

あとほぼ自分用になりますが、やりたいことから逆引きしてキーワードを整理しようと思ったのでそれも乗っけています。

**まだまだ触りたてなので、認識が怪しいところが多々あります。**

# その1 Vueインスタンスとは。

Vueは代表的には以下の要素をもつインスタンスです。

+ 紐づくDOM要素
+ 紐付いたDOMの中身を**基本的に上書き**するtemplateもしくはコンポーネント
+ 変数群をまとめたデータ
+ メソッド

他にも持たせることができますが、最も基本的なものはこれです。
コンポーネントに関しては一旦置いておきます。

最もベーシックなVueインスタンスはこんな感じになります。

```.js
new Vue({
  el: "#hoge", //DOM要素
  data:{ //データ
    data1:1,
    data2:"fuga"
  },
  methods:{ //メソッド
    hoge_function:function(){}
  },
  template:"some html in here" //テンプレート
})
```

んで、公式の最初の宣言的レンダリングの例を見てみましょう。

```.html
<div id="app">
  {{ message }}
</div>
```
```.js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})
```
この場合、テンプレートが無いのでhtmlは上書きされずに残ります。そしてhtmlの中にある

```
{{ message }}
```
にこのDOMに紐付いているVueインスタンスのdataが対応して表示されるという事になっています。
この時htmlとVueのデータはバインディングされていて、一方を変えるともう片方が変わります。
便利です。

ところがこれがわかってもHello Worldは全くわかりませんので、次のコンポーネントと単一ファイルコンポーネントの話に移ります。

# コンポーネント
コンポーネントはVueインスタンスを、他のVueインスタンスのパーツとして(子要素として)使う場合の特別な呼び名になっています(多分)。ちょっと簡単な例を出します。。

```.js
Vue.component('test-component', {
  data: function () {
    return {
      count: 0
    }
  },
  template: "hogehogeho-"
})
```
注意しなくてはならないのは**dataが関数になっている**ことくらいでしょうか。
それ以外は基本的に普通のVueインスタンスです。
コンポーネントは再利用前提なのでdataをインスタンスごとに別々になる関数で持たせることになっています。
さて、コンポーネントを使うのは簡単です。

```.html
<div id="comp">
  <test-component></test-component>
</div>
```
**上のように、コンポーネントを使うよ〜と明示したhtml要素と、その要素を対象にするVueインスタンスがあればよいです。**
公式の

https://jp.vuejs.org/v2/guide/components.html

ここの例ではそのような方式を非常にわかりやすい方法でとっています。
さて、Vue CLIでもガイドの通りにコンポーネントを試してみると…

**Vue CLIのデフォルトだとうまくいきません**

なぜか。Vue CLIのVueは軽量版で、**templateをhtmlに書き出すことができないからです**
(もう少し正確にはtemplate→render関数のコンパイルができない)

Vueをコンパイラを含んだものに変えてもいいのですが、重くなるので基本的には避けたいですよね。
これを回避できる方法が単一ファイルコンポーネントとrender関数の組み合わせです。

# 単一ファイルコンポーネント
単一ファイルコンポーネントは読んで字の通り、一つのファイルに一つのコンポーネントを書いたものです。

```.vue
<template></template>

<script></script>

<style></style>
```
みたいな感じで、コンポーネントの要素がhtmlっぽく記述されています。
この単一ファイルコンポーネントはコンポーネントの名前空間への登録や、render等の面で有利です。
試しに単純な単一ファイルコンポーネントを作ってみます。Vue CLIならcomponentsというフォルダが有るはずなのでその中に作ります。

```mycomp.vue
<template>
<div id="mycomp-div">
<h1>test of my component</h1>

I have {{ msg }} (from data)
</div>
</template>

<script>
export default {
    name:"mycomp",
    data:function(){
        return{
            msg: "hogehoge",
            data2 : 2
        }
    }    
}
</script>>
```
そしたら、Vue CLIのmain.jsを編集して自作コンポーネントを読み込みます。


```main.js
import mycomp from "./components/mycomp.vue"
new Vue({
  render: h => h(mycomp),
}).$mount('#app')
```

すると、自作コンポーネントのとおりになっているはずです。
これでHellow Worldが理解できるようになりました。


# Hellow Worldを理解する。
Hellow worldは単一ファイルコンポーネント２つ(App.vueとHelloWorld.vue)で構成されています。

そして、App.vueではHellowWorld.vueがコンポーネントとして採用されています。

```App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>
```
このようにscriptにimportを書くことで孫コンポーネントみたいなこともできるんですね。

# やりたいこと逆引き

## 配列全てに対してなんかしたい
ディレクティブ　v-for

## 要素の表示非表示を切り替えたい
ディレクティブ v-if もしくは　v-show
(v-ifはコンポーネントを実際に生成、破壊しているためコスト大。v-showはただの表示非表示)

## htmlの属性(classなど)を動的に変更したい
ディレクティブ　v-bind

## イベント処理
ディレクティブ　v-on

## 値の変更に反応するgetter setter
算出プロパティ　computed{}

## input要素
v-modelもしくはv-on+v-bind

## コンポーネントになにか初期化用の値を渡す。
静的な値　props[]
動的に渡す　v-bind

## コンポーネント内のdivなどに静的な文書を入れたい
slot

## 複数のコンポーネントの間で切り替えをしたい。
v-bind:is
切り替えたときに切り替える前の内部状態を保持しておきたいならkeep-aliveを使用

## 親コンポーネントから子コンポーネントのメソッド呼び出し
ref

## 子コンポーネントから親コンポーネントのメソッド呼び出し
emit

## render関数内でコンポーネントにプロパティを渡したりする
インスタンスプロパティ


そのうち増えるかもしれません。