跳轉到內容

優先順序D規則:謹慎使用

Vue中存在一些特性是為了適應罕見的邊緣情況或更平滑地從舊程式碼庫遷移。然而,過度使用這些特性可能會使你的程式碼更難維護,甚至成為bug的來源。這些規則突出了潛在的風險特性,並描述了何時以及為什麼應該避免使用它們。

帶有scoped的元素選擇器

應避免在scoped樣式中使用元素選擇器。

scoped樣式中,優先使用類選擇器而不是元素選擇器,因為大量元素選擇器會很慢。

詳細說明

為了作用域樣式,Vue會為元件元素新增一個唯一的屬性,例如data-v-f3f3eg9。然後修改選擇器,以便只選擇具有此屬性的匹配元素(例如button[data-v-f3f3eg9])。

問題是,大量的元素屬性選擇器(例如button[data-v-f3f3eg9])將比類屬性選擇器(例如.btn-close[data-v-f3f3eg9])慢得多,因此應儘可能優先使用類選擇器。

不好

模板
<template>
  <button>×</button>
</template>

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

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

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

隱式父子通訊

應優先使用props和events進行父子元件通訊,而不是使用this.$parent或修改props。

理想的Vue應用是props向下傳遞,events向上傳遞。堅持這個約定會使你的元件更容易理解。然而,在某些邊緣情況下,prop修改或this.$parent可以簡化已經深度耦合的兩個元件。

問題是,還有許多簡單的情況,這些模式可能會帶來便利。注意:不要因為短期的便利(寫更少的程式碼)而犧牲理解狀態流動的簡單性。

不好

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>
  `
})

不好

vue
<script setup>
defineProps({
  todo: {
    type: Object,
    required: true
  }
})
</script>

<template>
  <input v-model="todo.text" />
</template>
vue
<script setup>
import { getCurrentInstance } from 'vue'

const props = defineProps({
  todo: {
    type: Object,
    required: true
  }
})

const instance = getCurrentInstance()

function removeTodo() {
  const parent = instance.parent
  if (!parent) return

  parent.props.todos = parent.props.todos.filter((todo) => {
    return todo.id !== props.todo.id
  })
}
</script>

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

vue
<script setup>
defineProps({
  todo: {
    type: Object,
    required: true
  }
})

const emit = defineEmits(['input'])
</script>

<template>
  <input :value="todo.text" @input="emit('input', $event.target.value)" />
</template>
vue
<script setup>
defineProps({
  todo: {
    type: Object,
    required: true
  }
})

const emit = defineEmits(['delete'])
</script>

<template>
  <span>
    {{ todo.text }}
    <button @click="emit('delete')">×</button>
  </span>
</template>
優先順序D規則:謹慎使用已載入