Vue.js 中級編

おさらい

算出プロパティ

new Vue({
  el: '#app',

  data: {
    text: 'Vue.js is awesome'
  },

  computed: {
    upperText() {
      return this.text.toUpperCase()
    }
  }
})
<div id="#app">
  {{ upperText }}
</div>

プロパティとして
アクセスする

算出プロパティ メソッド
オプション名 computed methods
呼び出し方 プロパティ
{{ someProp }}
メソッド
{{ someMethod() }}
キャッシュ される されない
引数 なし あり

注意点

Date.now() など Vue.js 以外で値が変わるものを
算出プロパティの中で使うとうまく更新が反映されない

https://codepen.io/ktsn/pen/OoywbP?editors=1111

ウォッチャー

new Vue({
  el: '#app',

  data: {
    text: 'hello'
  },

  watch: {
    text(newValue, oldValue) {
      // this.text が変わったときに実行される
    }
  }
})
new Vue({
  // ...

  watch: {
    text: {
      handler(newValue, oldValue) {
        // this.text が変わったときに実行される
      },
      immediate: true, // 初期値設定時にも実行されるようにする
      deep: true // オブジェクトの子孫も監視する 
    }
  }
})

watch のオプション

// 文字列
vm.$watch('a.b.c', function (newVal, oldVal) {
  // vm.a.b.c が変更されたら実行される
})

// 関数
vm.$watch(
  function () {
    return this.a + this.b
  },
  function (newVal, oldVal) {
    // this.a + this.b の値が変わったら実行される
  }
)

ライフサイクル

例えば……

  • created でスライダーのページめくりのタイマーを起動
  • mounted で外部の UI ライブラリをマウント
  • beforeDestroy で↑のような処理を無効化

コンポーネント

Vue.component('v-button', {
  template: `...`,
  
  props: { /* ... */ },
  
  // ... インスタンスオプションと同様 ...
}

グローバルに登録

すべてのテンプレートで使えるようにする

const VButton = {
  template: `...`,
  
  props: { /* ... */ },
  
  // ... インスタンスオプションと同様 ...
}

// 他のコンポーネント
const AnotherComp = {
  // VButton を登録
  components: { VButton }
}

ローカルに登録

あるコンポーネントのテンプレートでのみ使えるようにする

Vue.component('v-button', {
  props: {
    // theme プロパティを定義
    // `this.theme` で参照できる
    theme: {
      type: String,
      default: null
    }
  },
  
  // ... インスタンスオプションと同様 ...
})

props

コンポーネントにデータを渡す

<!-- theme に 'blue' を渡す -->
<v-button theme="blue" />
Vue.component('v-button', {
  methods: {
    onClick () {
      // `click` イベントを送出
      this.$emit('click')
    }
  }
  
  // ... インスタンスオプションと同様 ...
})

カスタムイベント

コンポーネントの外側にイベントを通知

<!-- クリックを監視 -->
<v-button 
  v-on:click="onClickButton" 
/>
Vue.component('v-button', {
  // 一部省略
  template: `<button> 
    <span>
      <slot />
    </span>
  </button>`
  
  // ... インスタンスオプションと同様 ...
})

スロット

コンポーネントの小要素を指定の場所に配置

<!-- 小要素が slot と差し替わる -->
<v-button>
  ボタンテキスト
</v-button>
Vue.component('v-button', {
  // 初期データを返す関数
  data() {
    return {
      localData: 'hoge'
    }
  }
})

data の書き方の違い

初期データを返す関数にする必要がある

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

<template>
  <!-- コンポーネントのテンプレート -->
</template>

<script>
// コンポーネントオプション
export default {
  data () { /* ... */ }
}
</script>

<style>
/*  コンポーネントのスタイル */
</style>
<template lang="pug">
  //- Pug
  button.button(type="button")
    slot
</template>

<script lang="ts">
// TypeScript
import Vue from 'vue'
export default Vue.extend({
  data () { /* ... */ }
})
</script>

<style lang="scss">
/* SCSS */
.button {
  &_text {
  }
}
</style>

Scoped CSS

scoped とつけるとスタイルがコンポーネント外に漏れなくなる

<template>
  <button class="button">
    <slot />
  </button>
</template>

<style scoped>
/* このコンポーネントにのみ適用 */
.button {
  background-color: blue;
}
</style>

応用

既存ライブラリをコンポーネントにする

Further Reading

  • Vue.js 公式ガイド
    https://jp.vuejs.org/v2/guide/
     
  • Vue.js 公式クックブック
    https://jp.vuejs.org/v2/cookbook/
     
  • やわらかVue.js
    https://scrapbox.io/vue-yawaraka/
     
  • Vue.js入門 (技評の Web 連載)
    https://gihyo.jp/dev/serial/01/vuejs
     
  • Vue.js入門 基礎から実践アプリケーション開発まで
    9月22日発売

Vue.js 中級編

By katashin

Vue.js 中級編

  • 2,738