Правила приоритета D: Используйте с осторожностью
Vue предоставляет некоторые возможности, которые обеспечивают "плавный" процесс миграции с устаревшей кодовой базы и учитывают редкие случаи. Если их использовать слишком часто, они могут сделать код сложно поддерживаемым или могут быть источниками багов. Эти правила "освещают" рисковые возможности 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>