속성 바인딩)
HTML 속성을 동적 값에 바인딩 하려면 v-bind 디렉티브를 사용한다.
<div v-bind:id="dynamicId"></div>
엘리먼트의 id 속성은 컴포넌트 상태의 dynamicId 속성과 동기화 된다.
v-bind는 다음과 같이 생략이 가능하다.
<div :id="dynamicId"></div>
만약 다음과 같이 여러 속성을 나타내는 Javascript 객체가 있는 경우
data() {
return {
objectOfAttrs: {
id: 'container',
class: 'wrapper'
}
}
}
특별한 인자 없이 v-bind를 사용하여 단일 엘리먼트에 속성을 바인딩 할 수 있다.
<div v-bind="objectOfAttrs"></div>
다음과 같이 id와 class가 바인딩 된다.
이벤트 리스너)
v-on 디렉티브를 사용하여 DOM 이벤트를 수신할 수 있다.
<button v-on:click="increment">{{ count }}</button>
여기서 click의 인자는 수신할 이벤트의 이름이다.
v-on은 다음과 같이 단축 문법으로 사용 가능하다.
<button @click="increment">{{ count }}</button>
폼(form) 바인딩)
v-bind와 v-on을 함께 사용하면, form 안의 입력 엘리먼트에 양방향 데이터 바인딩을 만들 수 있다.
<input :value="text" @input="onInput">
<p>{{ text }}</p>
methods: {
onInput(e) {
// v-on 핸들러는 네이티브 DOM 이벤트를 인자로 받습니다.
this.text = e.target.value
}
}
입력란에 값을 입력하면 p 태그의 텍스트가 실시간으로 업데이트 된다.
Vue는 양방향 바인딩을 단순화하기 위해, 위 문법을 간편 표기하는 v-model 디렉티브를 제공한다.
<input v-model="text">
즉 v-model은 v-bind와 v-on을 합쳐놓은 것이라고 생각하면 된다.
v-model은 텍스트 입력 외에도 체크박스, 라디오 버튼, 셀렉트 드롭다운과 같은 다른 입력 타입에서도 사용할 수 있다.
(form 안의 요소에서 v-model을 사용한다고 생각하면 된다)
조건부 렌더링)
엘리먼트를 조건부로 렌더링하기 위해 v-if 디렉티브를 사용할 수 있다.
<h1 v-if="awesome">Vue는 굉장해! 엄청나!</h1>
awesome 값이 truthy인 경우에만 렌더링 된다.awesome 값이 falthy 값으로 변경되면 DOM에서 아예 제거된다. (태그 자체가 사라짐)
v-else나 v-else-if를 사용하여 조건에 따라 다르게 렌더링을 할 수 있다.
<h1 v-if="awesome">Vue는 굉장해! 엄청나!</h1>
<h1 v-else>오 안돼 😢</h1>
v-else 엘리먼트는 v-if 또는 v-else-if 엘리먼트 바로 다음에 와야 인식 됨.
v-else 및 v-else-if는 Rapper 역할을 하는 <template>에서도 사용할 수 있다.
<template v-if="ok">
<h1>제목</h1>
<p>단락 1</p>
<p>단락 2</p>
</template>
v-if와 유사한 기능을 하는 옵션으로 v-show가 있다.
<h1 v-show="ok">안녕!</h1>
v-show는 무조건 렌더링은 한다. 하지만 display 속성만 전환할 뿐이다.
v-show는 v-else와 상호작용하지 않음.
리스트 렌더링)
v-for 디렉티브를 사용하여 자료 배열을 엘리먼트 목록으로 렌더링할 수 있다.
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
todo는 현재 배열 엘리먼트에서 반복되는 지역 변수이다.
v-for 엘리먼트 또는 그 내부에서만 todo에 접근할 수 있다.
여기서는 todos라는 자료 배열의 요소를 하나를 꺼내서 todo라는 지역 변수에 담았고
todo의 id를 key로 사용하고 text를 출력했다.
각 todo 객체가 가지고 있는 id 값을 특별한 속성인 key에 바인딩했다.
key는 요소를 구별할 수 있는 unique한 내용을 사용해야 하며, key로 각 요소들을 구분할 수 있게 된다.
계산된 속성)
computed 옵션을 사용하여 반응적으로 계산되는 속성을 선언할 수 있다.
<script>
let id = 0
export default {
data() {
return {
newTodo: '',
hideCompleted: false,
todos: [
{ id: id++, text: 'HTML 배우기', done: true },
{ id: id++, text: 'JavaScript 배우기', done: true },
{ id: id++, text: 'Vue 배우기', done: false }
]
}
},
computed: {
filteredTodos() {
return this.hideCompleted
? this.todos.filter((t) => !t.done)
: this.todos
}
},
methods: {
addTodo() {
this.todos.push({ id: id++, text: this.newTodo, done: false })
this.newTodo = ''
},
removeTodo(todo) {
this.todos = this.todos.filter((t) => t !== todo)
}
}
}
</script>
<template>
<form @submit.prevent="addTodo">
<input v-model="newTodo" />
<button>할 일 추가</button>
</form>
<ul>
<li v-for="todo in filteredTodos" :key="todo.id">
<input type="checkbox" v-model="todo.done">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
<button @click="hideCompleted = !hideCompleted">
{{ hideCompleted ? '모두 보이기' : '완료된 항목 숨기기' }}
</button>
</template>
<style>
.done {
text-decoration: line-through;
}
</style>
computed 옵션에서,
filteredTodos() 메서드를 사용해서 반응적으로 계산되는 값을 return 할 수 있다.
v-for에서 filteredTodos의 결과값이 유동적으로 변하게 되고
따라서 렌더링 되는 list도 버튼을 클릭할 때마다 변하게 된다.
수명주기와 템플릿 참조)
DOM을 수동으로 작업해야 하는 경우, 특별한 속성인 ref를 사용하여 템플릿 참조를 할 수 있다.
<p ref="p">안녕</p>
하지만 컴포넌트가 마운트된 이후에만 ref를 통해 접근할 수 있다.
마운트 된 후에 실행될 코드는 mounted 옵션을 사용하면 된다.
export default {
mounted() {
this.$refs.p.textContent = 'Hello Vue.js!';
}
}
this.$refs.p 를 통해 p 태그에 접근하고, DOM을 조작하였다.
이와 같이 컴포넌트의 수명 주기의 특정 시간에 호출될 콜백을 등록할 수 있다.
수명주기에 관한 표는 다음을 참고한다.
감시자)
속성에 변화가 생겼을 때 watch 옵션을 사용해서 변경 사항을 감시하고 원하는 사이드 이펙트를 수행할 수 있다.
export default {
data() {
return {
count: 0
}
},
watch: {
count(newCount, oldCount) {
// 예, console.log()는 사이드 이펙트입니다.
console.log(`새로 센 숫자 값은: ${newCount}`)
console.log(`기존의 숫자 값은: ${oldCount}`)
}
}
}
watch에서 사용된 메서드(이름은 변화된 속성값으로 한다)의 첫 번째 인자는 새 값, 두 번째 인자는 기존 값이다.
컴포넌트)
상위 컴포넌트는 다른 컴포넌트를 템플릿의 하위 컴포넌트로 렌더링할 수 있다.
자식 컴포넌트를 사용하려면 먼저 import를 해서 가져오고, 상위 컴포넌트에서 등록을 해야 한다.
그리고 등록한 컴포넌트의 이름으로 템플릿에서 사용할 수 있다.
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
}
}
</script>
<template>
<!-- 자식 컴포넌트 렌더링 -->
<ChildComp/>
</template>
Props)
자식 컴포넌트는 props를 통해 부모로부터 데이터를 받을 수 있다.
우선, 허용할 props를 선언해야 한다.
// ChildComp.vue
<script>
export default {
props: {
msg: String
}
}
</script>
<template>
<h2>{{ msg || 'prop이 아직 전달되지 않았습니다!' }}</h2>
</template>
그리고 부모 컴포넌트에서 v-bind를 이용해 greeting 이라는 데이터를 자식 컴포넌트에 msg라는 prop으로 전달한다.
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
},
data() {
return {
greeting: '부모 컴포넌트로부터 💌을 전달받았어요!'
}
}
}
</script>
<template>
<ChildComp v-bind:msg="greeting"/>
</template>
Emits)
자식 컴포넌트는 부모로부터 props를 받는 것 뿐만 아니라 이벤트를 emit(발송)할 수도 있다.
// ChildComp.vue
export default {
// emit할 이벤트 선언
emits: ['response'],
created() {
// 인자와 함께 emit
this.$emit('response', '자식 컴포넌트로부터 🌷를 받았어요!')
}
}
자식 컴포넌트에 이벤트를 선언하고,
this.$emit(첫 번째 인자, 두 번째 인자(선택),...) 으로 이벤트를 발생시킨다.
created() 에 해당 코드를 사용했으므로
컴포넌트가 생성될 때 이벤트가 발생하게 된다.
첫 번째 인자는 이벤트의 이름이고, 이후 추가되는 모든 인자는 이벤트 리스너에 전달된다.
부모는 v-on을 사용하여 자식 컴포넌트에서 발송한 이벤트를 수신할 수 있다.
<ChildComp @response="(msg) => childMsg = msg" />
response라는 이벤트를 수신하면, 옆에 정의된 메서드를 실행시켜서 childMsg를 msg로 변경하게 된다.
// ChildComp.vue
<script>
export default {
emits: ['response'],
created() {
this.$emit('response', '자식 컴포넌트로부터 🌷를 받았어요!')
}
}
</script>
<template>
<h2>자식 컴포넌트</h2>
</template>
// App.vue
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
},
data() {
return {
childMsg: '자식 컴포넌트로부터 아직 메시지를 받지 못했어요!'
}
},
}
</script>
<template>
<ChildComp v-on:response="(msg) => childMsg = msg"/>
<p>{{ childMsg }}</p>
</template>
슬롯)
부모 컴포넌트는 자식에게 props를 사용하여 데이터를 전달하는 것 외에도,
슬롯을 사용하여 템플릿 조각을 전달할 수 있다.
// ChildComp.vue
<template>
<slot>대체: 부모로부터 컨텐츠를 못 받았어요! 😢</slot>
</template>
// App.vue
<script>
import ChildComp from './ChildComp.vue'
export default {
components: {
ChildComp
},
data() {
return {
msg: 'Vue는 개발자에게 정말 유용하죠! 🎁'
}
}
}
</script>
<template>
<ChildComp>{{ msg }}</ChildComp>
</template>
'간단 요약' 카테고리의 다른 글
221206 SQLD 학습 (0) | 2022.12.07 |
---|---|
데이터 모델링 Day 1 (0) | 2022.08.01 |
220404 Java 14장 스트림 간단 요약 (0) | 2022.04.05 |