Vue チュートリアルを触ってみる 「はじめに」編

公式サイトの[チュートリアル](https://jp.vuejs.org/v2/guide/)から始めてみる。

初心者はvue-cliは使うべきではないと書いているが、逆らってvue-cliで始めてみるので、チュートリアルとは違ったりする。

まずは、vue-cliの各ファイルを覗いてみる。

main.jsが文字通りメインっぽい。処理の始まりって感じかな。

```main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

```

App.vueはこんな感じ。`<router-view>`って何？

```App.vue
<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
```

どうやら`router/index.js`でルーティングを設定していて、`HelloWorld`コンポーネントがルートに設定されている。インデックスページにアクセスすると、`HelloWorld.vue`の内容が展開されるっぽい。

```router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

```

## テンプレート構文

テンプレート構文を使ってみる。`{{}}`これのことかな。

```components/HelloWorld.vue
<template>
  <p>{{ message }}</p>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      message: 'hello world'
    }
  }
}
</script>
```

## ディレクティブ

### v-bind

ここで使っている`v-bind`のように`v-`から始まる属性は**ディレクティブ**と呼ばれるらしい。

```components/HelloWorld.vue
<template>
  <p v-bind:title="message">title属性にmessageをbindしてるから、この文章にホバーするとmessageの内容が表示される。</p>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      message: 'hello world'
    }
  }
}
</script>
```

### v-if

`seen`プロパティを`false`にすると表示されず、`true`にすると表示される。

```components/HelloWorld.vue
<template>
  <p v-if="seen">これが見えるかな？</p>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      seen: false
    }
  }
}
</script>
```

### v-for

チュートリアルには無いが、`:key`が無いと怒られるので追加。

```components/HelloWorld.vue
<template>
  <ol>
    <li v-for="todo in todos" :key="todo.text">{{ todo.text }}</li>
  </ol>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      todos: [
        { text: 'やること1' },
        { text: 'やること2' },
        { text: 'やること3' }
      ]
    }
  }
}
</script>
```

### v-on

`addEventListener`的な感じ。イベントを登録することができる。

```components/HelloWorld.vue
<template>
  <div class="wrapper">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage">反対にする</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      message: 'だまや'
    }
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
}
</script>
```

### v-model

これこそ、**双方向データバインディング**と呼ばれるもの。データを変更するとリアルタイムに表示が変わる。

```components/HelloWorld.vue
<template>
  <div class="wrapper">
    <p>{{ message }}</p>
    <input v-model="message">
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      message: 'Hello'
    }
  }
}
</script>
```

## コンポーネントを作成

TodoItem.vueファイルを作成。

```components/TodoItem.vue
<template>
  <li>This is a todo</li>
</template>

<script>
export default {
  name: 'TodoItem'
}
</script>
```

## コンポーネントを使用

```components/HelloWorld.vue
<template>
  <div class="wrapper">
    <ol>
      <todo-item></todo-item>
    </ol>
  </div>
</template>

<script>
import TodoItem from './TodoItem'

export default {
  name: 'HelloWorld',
  components: { TodoItem },
  template: '<todo-item>',
  data () {
    return {
      message: 'Hello'
    }
  }
}
</script>
```

### 親のスコープから子コンポーネントにデータを渡す

```components/TodoItem.vue
<template>
  <li>{{ todo.text }}</li>
</template>

<script>
export default {
  name: 'TodoItem',
  props: ['todo']
}
</script>
```

```components/HelloWorld.vue
<template>
  <div class="wrapper">
    <ol>
      <todo-item v-for="item in groceryList" v-bind:todo="item" :key="item.text"></todo-item>
    </ol>
  </div>
</template>

<script>
import TodoItem from './TodoItem'

export default {
  name: 'HelloWorld',
  components: { TodoItem },
  template: '<todo-item>',
  data () {
    return {
      message: 'Hello',
      groceryList: [
        { id: 0, text: '野菜' },
        { id: 1, text: 'チーズ' },
        { id: 2, text: '食べれるものならなんでも' }
      ]
    }
  }
}
</script>
```

親コンポーネントと子コンポーネントのファイルを同列に作成したが、本来であれば別にするべきだろうなぁ。