知海

谨慎使用规则

Vue风格指南

优先级 D 规则:谨慎使用 {#priority-d-rules-use-with-caution}

Vue 的某些特性是为了适应罕见的边缘情况或从遗留代码库更平滑地迁移而存在的。然而,过度使用它们可能会使你的代码更难维护,甚至成为 bug 的来源。这些规则揭示了潜在有风险的特性,说明了应何时以及为何避免使用它们。

scoped 的元素选择器 {#element-selectors-with-scoped}

应避免在 scoped 中使用元素选择器。

scoped 样式中,建议优先使用类选择器而非元素选择器,因为大量的元素选择器会拖慢渲染速度。

::: details 详细说明
为了限定样式的作用范围,Vue 会给组件元素添加一个唯一属性,例如 data-v-f3f3eg9。然后选择器会被修改,以便仅选中带有此属性的匹配元素(例如 button[data-v-f3f3eg9])。

问题在于,大量的元素-属性选择器(例如 button[data-v-f3f3eg9])会比类-属性选择器(例如 .btn-close[data-v-f3f3eg9])慢得多。因此,只要可能,应优先使用类选择器。
:::

不推荐

vue-html 复制代码
<template>
  <button>×</button>
</template>

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

推荐

vue-html 复制代码
<template>
  <button class="btn btn-close">×</button>
</template>

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

隐式的父子组件通信 {#implicit-parent-child-communication}

父子组件之间的通信应优先使用 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 复制代码
<template>
  <input v-model="todo.text" />
</template>
vue 复制代码
<template>
  <span>
    {{ todo.text }}
    <button @click="renameTodo">rename</button>
  </span>
</template>

推荐

vue 复制代码
<template>
  <input :value="todo.text" @input="emit('input', $event.target.value)" />
</template>
vue 复制代码
<template>
  <span>
    {{ todo.text }}
    <button @click="renameTodo">rename</button>
  </span>
</template>

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。