本文へジャンプ

優先度D: 注意深く使用する

Vue のいくつかの機能は、まれなエッジケースに対応するため、またはレガシーコードベースからの移行をよりスムーズにするために存在します。しかし使いすぎると、コードのメンテナンスが難しくなったり、バグの原因になったりすることがあります。これらのルールは、潜在的にリスクの高い機能に注目し、いつ、なぜ、それらを避けるべきかを説明します。

scoped 付きの要素セレクター

要素セレクターは scoped で使わないようにしてください。

大量の要素セレクターは遅いので scoped スタイルでは要素セレクターよりもクラスセレクターを使うようにしてください。

詳しい説明

scope スタイルに対し、Vue はコンポーネント要素に data-v-f3f3eg9 のようなユニークな属性を追加します。そしてセレクターはこの属性にマッチする要素のみが選択されるように修正されます(例: button[data-v-f3f3eg9])。

大量の要素属性セレクター(例: button[data-v-f3f3eg9])はクラス属性セレクター(例: .btn-close[data-v-f3f3eg9])に比べてかなり遅いという問題があるので、できる限りクラスセレクターを使うようにしてください。

悪い例

template
<template>
  <button>×</button>
</template>

<style scoped>
button {
  background-color: red;
}
</style>

良い例

template
<template>
  <button class="btn btn-close">×</button>
</template>

<style scoped>
.btn-close {
  background-color: red;
}
</style>

暗黙の親子間通信

親子間のコンポーネントの通信には、プロパティを変更したり this.$parent を使うのではなく、プロパティとイベントを使うようにしてください。

理想的な Vue アプリケーションは props down, events up です。この規約に従うことでコンポーネントはより理解しやしくなります。しかし、プロパティの変更や this.$parent を使うことですでに深く結合している 2 つのコンポーネントを単純化できるようなエッジケースが存在します。

問題はこれらのパターンが便利になる シンプル なケースも多く存在することです。注意: 短期的な利便性(少ないコードを書くこと)のために単純な取引(状態の流れを理解できること)するよう誘惑されないでください。

悪い例

js
app.component('TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },

  template: '<input v-model="todo.text">'
})
js
app.component('TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },

  methods: {
    removeTodo() {
      this.$parent.todos = this.$parent.todos.filter(
        (todo) => todo.id !== vm.todo.id
      )
    }
  },

  template: `
    <span>
      {{ todo.text }}
      <button @click="removeTodo">
        ×
      </button>
    </span>
  `
})

良い例

js
app.component('TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },

  emits: ['input'],

  template: `
    <input
      :value="todo.text"
      @input="$emit('input', $event.target.value)"
    >
  `
})
js
app.component('TodoItem', {
  props: {
    todo: {
      type: Object,
      required: true
    }
  },

  emits: ['delete'],

  template: `
    <span>
      {{ todo.text }}
      <button @click="$emit('delete')">
        ×
      </button>
    </span>
  `
})
優先度D: 注意深く使用するが読み込まれました