Regras Prioridade D: Use com Cautela
Algumas funcionalidades do Vue existem para acomodar casos extremos raros ou suavizar migrações de uma base de código legado. Entretanto, ao serem utilizadas excessivamente, elas podem tornar o seu código mais difícil de manter ou até mesmo se tornarem uma fonte de bugs. Estas regras demonstram funcionalidades possivelmente arriscadas, descrevendo quando e porquê elas devem ser evitadas.
Seletores de elemento com scoped
Seletores de elemento devem ser evitados com scoped
.
Prefira seletores de classe em vez de seletores de elemento nos estilos scoped
, porque um grande número de seletores de elemento diminuem a velocidade.
Explicação Detalhada
Para definir estilos em escopo, o Vue adiciona um atributo único aos elementos componentes, algo como data-v-f3f3eg9
. Então os seletores são modificados para que apenas elementos correspondentes com este atributo sejam selecionados (e.g. button[data-v-f3f3eg9]
).
O problema é que um grande número de seletores elemento-atributo (e.g. button[data-v-f3f3eg9]
) serão consideravelmente mais lentos do que seletores classe-atributo (e.g. .btn-close[data-v-f3f3eg9]
), então seletores de classe devem ser escolhidos sempre quando possível.
Ruim
template
<template>
<button>×</button>
</template>
<style scoped>
button {
background-color: red;
}
</style>
Bom
template
<template>
<button class="btn btn-close">×</button>
</template>
<style scoped>
.btn-close {
background-color: red;
}
</style>
Comunicação pai-filho implícita
Props e eventos devem ser preferíveis para a comunicação entre componentes pai-filho, ao invés de this.$parent
ou de realizar mutações em props.
Uma aplicação Vue ideal segue props para baixo, eventos para cima. Manter-se a esta convenção tornará os seus componentes mais fáceis de se entender. Entretanto, existem casos extremos em que a mutação de props ou this.$parent
pode simplificar dois componentes já profudamente acoplados.
O problema é, há muitos outros casos simples onde esses padrões podem ser convenientes. Cuidado: não fique tentando a trocar simplicidade (estar apto a entender o fluxo do seu estado) por conveniência a curto-prazo (escrever menos código).
Ruim
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>
`
})
Bom
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>
`
})