Правила приоритета D: Используйте с осторожностью
Некоторые функции Vue существуют для того, чтобы учесть редкие крайние случаи или сгладить миграцию с унаследованной кодовой базы. Однако при чрезмерном использовании они могут усложнить сопровождение кода или даже стать источником ошибок. Эти правила проливают свет на потенциально рискованные функции, описывая, когда и почему их следует избегать.
Селекторы элементов с scoped
Селекторы элементов следует избегать с scoped.
Предпочитайте селекторы классов селекторам элементов в scoped стилях, потому что большое количество селекторов элементов работает медленно.
Подробное объяснение
Чтобы охватить стили, 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 — параметры вниз, события вверх. Придерживаясь этой конвенции, вы значительно упростите понимание компонентов. Однако есть крайние случаи, когда мутация параметров или this.$parent могут упростить два компонента, которые уже глубоко связаны между собой.
Проблема в том, что существует множество простых случаев, когда эти шаблоны могут предложить удобство. Остерегайтесь: Не поддавайтесь соблазну променять простоту (возможность понять поток вашего состояния) на краткосрочное удобство (написание меньшего количества кода).
Плохо
vue
<script setup>
defineProps({
todo: {
type: Object,
required: true
}
})
</script>
<template>
<input v-model="todo.text" />
</template>vue
<script setup>
const props = defineProps({
todo: {
type: Object,
required: true
}
})
function renameTodo() {
// Изменяет реактивный объект родителя через проп
// Другими словами, дочерний компонент напрямую залезает и меняет состояние, которое принадлежит родителю.
props.todo.text = 'переименовано потомком'
}
</script>
<template>
<span>
{{ todo.text }}
<button @click="renameTodo">переименовать</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>
const props = defineProps({
todo: {
type: Object,
required: true
}
})
const emit = defineEmits(['update:todo'])
function renameTodo() {
// Передаем новый объект — обновление принадлежит родителю.
emit('update:todo', { ...props.todo, text: 'переименовано родителем' })
}
</script>
<template>
<span>
{{ todo.text }}
<button @click="renameTodo">переименовать</button>
</span>
</template>