vue-cliでVue.jsに入門して小さなアプリを作った

Vue.jsちょっと触ってみるかと思い立ったので、ビルド周りが面倒じゃなさそうなvue-cliを使って入門した。
で出来上がったのがこれ。
J-WAVE NOW ON AIR
Github

J-WAVEの最新オンエア曲20曲を表示して、各曲情報にYouTubeの検索結果のリンクをつけただけの小さなアプリ。以下今回覚えたことのメモ。

単一ファイルコンポーネント

.vueファイルで作られるコンポーネント。
すごいシンプルなコンポーネントだと以下のようになる。

<template>
  <div class="greeting">Hello<div>
</template>

<script>
  export default {
    name: 'Hello'
  }
</script>

<style scoped>
  .greeting {
    font-weight: bold;
  }
</style>

templateタグ内にはこのコンポーネントが表示するHTMLを書く。

scriptタグ内にはこのコンポーネントが持つメソッドとか色々書く(後述)。nameではコンポーネントの名前を定義している。

styleタグ内にstyleを定義していく。styleタグにscoped属性を付けると、各タグにdata-v-319a0ec5みたいな属性が自動で振られて、以下のようなセレクタに変換される。

.greeting[data-v-319a0ec5] {
  font-weight: bold;
}

よって他コンポーネントに同じ名前のクラスを定義してもぶつからない。

他のコンポーネントをimportする

他のコンポーネントをimportして使用したい場合は

<template>
  <Btn />
</template>
<script>
  import Btn from './Btn.vue'
  export default {
    name: 'Navigation',
    components: {
      Btn
    }
  }
</script>

のようにする。importして使用するコンポーネントをcomponentsに登録する必要がある。

methods

コンポーネント内で使用する関数はmethodsで定義する。

<script>
  export default {
    name: 'Btn',
    methods: {
      clickHandler: function () {
        alert('hoge')
      }
    }
  }
</script>

data

Reactで言うとこのstate。このコンポーネントが保持する状態を定義する。

<script>
  export default {
    name: 'Hello',
    data: function () {
      return {
        greeting: 'Hello'
      }
    }
  }
</script>

dataの値をtemplate内で展開する

dataで保持している値をtemplate内で展開する場合は波括弧を使う。

<template>
  <div class="greeting">{{ greeting }}</div>
</template>

画像のsrcなど属性系は波括弧使わないで以下の様に

<template>
  <img :src="item.image" />
</template>

条件付きレンダリング

何かしらの条件によって表示したりしなかったりする。 v-if を使う。
以下は画像URLが空じゃなければimg要素を表示する、みたいな例。

<template>
  <img :src="item.image" v-if="item.image.length > 0" />
</template>

for

配列からリスト作りたいときは v-for を使う。
keyにはユニークな値をセット。このへんもReactと変わらない。

<template>
  <div class="greeting" v-for="item in greetings" :key="item.id">{{ item.text }}</div>
</template>
<script>
  export default {
    name: 'Hello',
    data: function () {
      return {
        greetings: [
          {
            id: 123,
            text: 'Hello'
          },
          {
            id: 456,
            text: 'Good Afternoon'
          },
          {
            id: 789,
            text: 'Good Night'
          },
        ]
      }
    }
  }
</script>

子コンポーネントにpropsを渡す

子コンポーネントにpropsとして何かを渡したい場合は

:props名="値"

とすればよい。

<template>
  <Btn :text="delete.title" />
</template>
<script>
  import Btn from './Btn.vue'
  export default {
    name: 'Navigation',
    components: {
      Btn
    },
    data: function () {
      return {
        delete: {
          title: '削除'
        },
      }
    }
  }
</script>

イベント

イベントは v-on:イベント名=”関数名” または @イベント名=”関数名” を使う

<template>
  <div @click="clickHandler">Button</div>
</template>
<script>
  export default {
    name: 'Navigation',
    methods: {
      clickHandler: function () {
        alert('hoge')
      }
    }
  }
</script>

親コンポーネントのメソッドを呼ぶ

親コンポーネントで定義されているメソッドを子コンポーネントから呼びたい場合は
親コンポーネント内でカスタムイベントを定義し、そのイベントに呼びたいメソッドを紐づけておく。
子コンポーネントはそのカスタムイベントを発火させることで親のメソッドを呼べるようになる。

<template>
  <Btn @my-event="myEventHandler" />
</template>
<script>
  import Btn from './Btn.vue'

  export default {
    name: 'Navigation',
    components: {
      Btn
    },
    methods: {
      myEventHandler: function (message) {
        alert(message)
      }
    }
  }
</script>

<template>
  <div @click="clickHandler">Button</div>
</template>
<script>
  export default {
    name: 'Btn',
    methods: {
      clickHandler: function () {
        this.$emit('my-event', 'hello')
      }
    }
  }
</script>

this.$emit でカスタムイベントを発火させている。2番目の引数を使って親に値を渡すこともできる。

参考記事

Vue.js
ラジオの「(非公式な)オンエア曲 BOT」を気が向いて作った話