우선 순위 D 규칙: 주의해서 사용하기
Vue의 일부 기능은 드문 에지 케이스에 대응하거나 레거시 코드베이스에서 원활하게 마이그레이션하도록 돕기 위해 존재합니다. 그러나 과도하게 사용되면 코드를 유지 관리하기 어렵게 만들거나 심지어 버그의 원인이 될 수 있습니다. 이 규칙들은 잠재적으로 위험한 기능이 무엇인지 밝히고, 언제, 왜 피해야 하는지 설명합니다.
scoped에서의 요소 선택자
scoped에서는 요소 선택자를 피해야 합니다.
scoped 스타일에서는 요소 선택자보다 클래스 선택자를 선호합니다. 왜냐하면 많은 수의 요소 선택자는 처리 속도가 느리기 때문입니다.
상세한 설명
스타일을 범위 지정하기 위해, Vue는 컴포넌트(component) 앨리먼트에 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를 사용하거나 prop을 변형하는 대신, prop과 이벤트를 사용하는 것을 선호해야 합니다.
이상적인 Vue 애플리케이션은 prop을 통해 아래로 전달하고, 이벤트를 통해 위로 전달합니다. 이 관례를 따르면 컴포넌트를 이해하기 훨씬 쉬워집니다. 그러나 prop 변형이나 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() {
// prop을 통해 부모의 반응형 객체를 변경합니다.
// 다시 말해, 자식이 부모가 소유한 상태에 접근하여 변경하는 것입니다.
props.todo.text = 'renamed by child'
}
</script>
<template>
<span>
{{ todo.text }}
<button @click="renameTodo">rename</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합니다. 업데이트는 부모가 소유합니다.
emit('update:todo', { ...props.todo, text: 'renamed by parent' })
}
</script>
<template>
<span>
{{ todo.text }}
<button @click="renameTodo">rename</button>
</span>
</template>