[DAY-36] Vue (3)
๐ ํท๊ฐ๋ ธ๋ & ๋ชฐ๋๋ ๋ถ๋ถ๋ค๋ง ์ ๋ฆฌํ๋ ๋๋ง์ TIL
๐ฏ ๋ชจ๋ ๊ฐ์ ๋ด์ฉ์ ์ ์ง ์์์!
์ค๋์ ์๊ฐ์?
Vanilla JS๋ก ๋ง๋ค์๋ ํ๋ก์ ํธ๋ ํ๋ ํ๋ ๋ค ์ค์ ํด์คฌ์ด์ผ ํ๋๊ฑธ
Vue๋ ๋ช๊ฐ์ ์์์ด๋ง์ผ๋ก ๋ชจ๋ ๊ฑธ ๋์์ํต๋๋ค.
์ ๊ธฐํด์..์ด๊ฒ ๋ฐ๋ก ๊ฑฐ๋ํ ํ๋์์ํฌ์ ์ธ๊ณ์ธ๊ฐ์?
[1] ์กฐ๊ฑด๋ถ ๋ ๋๋ง
[1-1] v-if
v-if, v-else-if, v-else
๋๋ ํฐ๋ธ๋ฅผ ์ด์ฉํด์ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ด ๊ฐ๋ฅํฉ๋๋ค.
<h1 v-if="isShow1">Hello Vue</h1>
<h2 v-else-if="isShow2">Hello Vue2</h2>
<h1 v-else>Hello Vue2</h1>
์ด๋, v-else-if
์ ์ฐ๊ฒฐ๋ ์์๋ค์ด ์ฌ๋ฌ๊ฐ์ผ ๊ฒฝ์ฐ, ์๋ก์ด ์์๋ก ๋ํํ ์ ์์ต๋๋ค.
์๋ก์ด ์์๊ฐ ๋ฐ์๋์ง ์๊ธธ ์ํ๋ฉด template
ํ๊ทธ๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค.
template
ํ๊ทธ๋ ์์ ์์๋ค๋ง ์ถ๋ ฅํ๊ณ , ๋ณธ์ธ์ ์ถ๋ ฅ๋์ง ์์ต๋๋ค.
<h1 v-if="isShow1">Hello Vue</h1>
<template v-else-if="isShow2">
<h2>Hello Vue2</h2>
<h3>Hello</h3>
<h4>Hello Hello</h4>
</template>
<h1 v-else>Hello Vue2</h1>
์ด๋ v-if
๋ฌธ์ ์์๋ฅผ ์์ ํ๋ฉด์์ ์ฌ๋ผ์ง๊ฒ ๋ง๋ญ๋๋ค.
์์์ ๊ตฌ์กฐ ์์ฒด๋ฅผ ์ฃผ์์ผ๋ก ๋ณํ์ํต๋๋ค.
[*] ํน์ง
๋ฐ์ดํฐ๊ฐ false์ธ ๊ฒฝ์ฐ, ๋ ๋๋ง ์์ฒด๊ฐ ๋์ง ์์ผ๋ฏ๋ก ์ด๊ธฐ ๋ ๋๋ง ๋น์ฉ์ด ๋ฎ์ต๋๋ค.
ํ์ง๋ง ๋ฐ์ดํฐ์ ๊ฐ์ด ๋ณํ ๋, ๋ ๋๋ง ์์ฒด๊ฐ ๋ค์ ์ผ์ด๋๋ฏ๋ก ์ ํ ๋น์ฉ์ด ๋์ต๋๋ค.
v-if
์ v-for
์ ํจ๊ป ์ฌ์ฉ๋๋ ๊ฒ์ด ๊ถ์ฅ๋์ง ์์ต๋๋ค.
ํจ๊ป ์ฌ์ฉํ๋ฉด v-if
๊ฐ ๋ ๋์ ์ฐ์ ์์๋ฅผ ๊ฐ์ ธ ์ํ๋ ๋์์ด ์ผ์ด๋์ง ์์ ์ ์์ต๋๋ค.
- ์ฌ๋ฐ๋ฅด์ง ์์ ์ฌ์ฉ๋ฒ
<ul>
<li v-for="user in users" v-if="user.isActive" :key="user.id">
{{ user.name }}
</li>
</ul>
- ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ๋ฒ
<ul>
<li v-for="user in activeUsers" :key="user.id">{{ user.name }}</li>
</ul>
<ul>
<template v-for="user in users" :key="user.id">
<li v-if="user.isActive">{{ user.name }}</li>
</template>
</ul>
[1-2] v-show
v-show
๋๋ ํฐ๋ธ๋ ์์์ ์คํ์ผ ์์ฑ display
๋ฅผ ์กฐ์ ํฉ๋๋ค.
<h1 v-show="isShow">Hello Vue</h1>
์์๊ฐ ์์ ํ๋ฉด์์ ์ฌ๋ผ์ง๋ ๊ฒ์ด ์๋, ์์์ display
์์ฑ ๊ฐ์ none
์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
[*] ํน์ง
๋ฐ์ดํฐ๊ฐ false์ธ ๊ฒฝ์ฐ์๋ ๋ ๋๋ง์ ๋ ์๋ ์ํ์ด๋ฏ๋ก ์ด๊ธฐ ๋ ๋๋ง ๋น์ฉ์ ๋์ต๋๋ค.
ํ์ง๋ง ์คํ์ผ ์์ฑ์ ๊ฐ์ผ๋ก ๋ณด์ฌ์ง๋ ์ฌ๋ถ๊ฐ ์ ํด์ง๊ธฐ ๋๋ฌธ์ ์ ํ ๋น์ฉ์ ๋ฎ์ต๋๋ค.
v-show
์ ๊ฒฝ์ฐ, ์์๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ์์ฑํ ํ ๋ฐ์ดํฐ๋ฅผ ์
ํ๊ธฐ ๋๋ฌธ์
์ด์ค ์ค๊ดํธ ํ๋ฉด์ ํ ์คํธ๊ฐ ๊ทธ๋๋ก ์ถ๋ ฅ๋๋ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ v-cloak
๋๋ ํฐ๋ธ์ ๊ฐ์ด ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
<h1 v-show="isShow" v-cloak>{{ msg }}</h1>
<!-- isShow, msg์ ์ฌ์ฉํ ์ค๋น๊ฐ ๋ชจ๋ ๋๋ ํ์ v-cloak๋ ์ฌ๋ผ์ง๋๋ค. -->
[v-cloak] {
display: none;
}
- v-cloak
์ปดํฌ๋ํธ์ ๋ฐ์ดํฐ๊ฐ ์์์ ์ฐ๊ฒฐ์ด ๋์ด ์๊ณ , ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ค๋น๊ฐ ๋ชจ๋ ๋์์ผ๋ฉด
์๋์ผ๋ก ์ ๊ฑฐ๋๋ ๋๋ ํฐ๋ธ์ ๋๋ค.
๋ฐ๋ผ์ ์ฐ๊ฒฐ๋ ์ปดํฌ๋ํธ ๋ฐ์ดํฐ๋ค์ด ์ปดํ์ผ์ ์๋ฃํ ๋ ๊น์ง ์๋ฆฌ๋จผํธ์ ๋จ์์์ต๋๋ค.
ํ ๊ธ๋๋ ๋น์ค์ด ๋์ผ๋ฉด v-show๋ฅผ, ํ ๊ธ๋๋ ๋น์ค์ด ๋ฎ์ผ๋ฉด v-if๋ฅผ ์ฌ์ฉํฉ๋๋ค.
[2] ๋ฆฌ์คํธ ๋ ๋๋ง
[2-1] ๋ฐฐ์ด ์ํ
v-for
๋๋ ํฐ๋ธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฐ์ด์ ๊ธฐ๋ฐ์ผ๋ก ๋ฆฌ์คํธ๋ฅผ ๋ ๋๋งํ ์ ์์ต๋๋ค.
item on items
ํํ์ ๋ฌธ๋ฒ์ ํ์๋ก ํฉ๋๋ค.
์ด๋, item ์ด์ธ์ index๋ฅผ ํ์๋ก ํ๋ค๋ฉด (item, index) on items
ํํ๋ก ์ ์ ์ ์์ต๋๋ค.
๋ํ JS์ ์ดํฐ๋ ์ดํฐ ๊ตฌ๋ฌธ๊ณผ ๋์ผํ๊ฒ item of items
์ ํํ๋ก๋ ์ ์ ์ ์์ต๋๋ค.
[2-2] ๊ฐ์ฒด ์ํ
๊ฐ์ฒด์ ์ํ๋ ๊ฐ๋ฅํฉ๋๋ค.
์ด๋ value, key์ ๋ํ ์กฐํ๋ฅผ ๊ฐ๋ฅ์ผ ํ๊ธฐ ์ํด (value, key) in myObject
์ ํํ๋ฅผ ์ง์ํฉ๋๋ค.
key, value ์ด์ธ์ index๋ฅผ ํ์๋ก ํ๋ค๋ฉด (value, key, index) in myObject
์ ํํ๋ก ์ ์ ์ ์์ต๋๋ค.
[2-3] ์ํ ์ ์ง
v-for
์ ์ด์ฉํด์ ๋ ๋๋ง๋ ์๋ฆฌ๋จผํธ ๋ชฉ๋ก์ ๊ฐฑ์ ํ ๋, ๊ธฐ๋ณธ์ ์ผ๋ก Vue๋ ๋๋ฆ์ ์ต์ ํ ๊ณผ์ ์ ๊ฑฐ์นฉ๋๋ค. (in-place patch)
ํญ๋ชฉ์ ์์๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ, ํญ๋ชฉ์ ์์์ ์ผ์นํ๋๋ก DOM ์์ ์์ฒด๋ฅผ ์ด๋ํ๋ ๊ฒ์ด ์๋,
Vue๋ ํด๋น ํญ๋ชฉ๋ค์ ์ ์ ํ ์์น์ ํจ์นํ๊ณ ํด๋น ์ธ๋ฑ์ค์์ ๋ ๋๋งํ ๋ด์ฉ์ ๋ฐ์ํ๋์ง ํ์ธํฉ๋๋ค.
์ด ๊ณผ์ ์์ ์ฝ๊ฐ์ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ๊ฐ ์์ดํ
์ ์ ์ผํ key
์์ฑ์ ๋์ด Vue์ ์ต์ ํ ๊ณผ์ ์ ๋์์ ์ค ์ ์์ต๋๋ค.
<div v-for="item in items" :key="item.id">...</div>
[2-4] ๋ฐฐ์ด ๋ณ์ด ๋ฉ์๋
Vue๋ ๋ฐฐ์ด์ ๋ณ์ด ๋ฉ์๋๋ก ์ธํ ๋ณ๊ฒฝ์ ๋ํํ์ฌ ๋ทฐ๋ฅผ ๊ฐฑ์ ํ ์ ์์ต๋๋ค.
[1] ๋ณ์ด ๋ฉ์๋
๋ณ์ด ๋ฉ์๋๋ ํธ์ถ๋ ์๋ ๋ฐฐ์ด์ ๋ณ๊ฒฝํฉ๋๋ค.
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
[2] ๋ฐฐ์ด ๊ต์ฒด ๋ฉ์๋ (๋น ๋ณ์ด ๋ฉ์๋)
๊ต์ฒด ๋ฉ์๋๋ ์๋ก์ด ๋ฐฐ์ด์ ๋ฐํํฉ๋๋ค.
- filter()
- concat()
- slice()
ํด๋น ๋ฉ์๋๋ค๋ก ํํฐ๋ง๋๊ฑฐ๋ ์ ๋ ฌ๋ ๋ฐฐ์ด์ ํ์ํ๊ธฐ ์ํด computed
์์ฑ์ ์ด์ฉํฉ๋๋ค.
computed
์์ฑ์ ์ด์ฉํ์ง ๋ชปํ ์ํฉ์์๋ methods
์ ํจ์๋ฅผ ์ ์ํด์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
[2-5] ๋ฒ์ ์ํ
์ผ๋ฐ์ ์ธ for๋ฌธ์ฒ๋ผ v-for๋ ์ ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒ์๋ฅผ ์ํํ ์ ์์ต๋๋ค.
<p v-for="n in 10">{{ n }}</p>
<!-- ์ด ๊ฒฝ์ฐ 1๋ถํฐ 10๊น์ง ์ถ๋ ฅ๋ฉ๋๋ค. -->
[3] ์ด๋ฒคํธ ํธ๋ค๋ง
v-on
(์ฝ์ด: @) ๋๋ ํฐ๋ธ๋ก ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๋ค๊ฐ ํธ๋ฆฌ๊ฑฐ์ํฌ ์ ์์ต๋๋ค.
[3-1] ์ธ๋ผ์ธ ๋ฉ์๋ ํธ๋ค๋ฌ
๋๋ก ์ธ๋ผ์ธ ๋ช ๋ น๋ฌธ ํจ๋ค๋ฌ์์ ์๋ณธ DOM ์ด๋ฒคํธ์ ์ ๊ทผํด์ผ ํ๋ ์ผ์ด ๋ฐ์ํฉ๋๋ค.
์ด๋ $event
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
<button @click="warn('Warnning', $event)">Submit</button>
// ...
methods: {
warn(msg, event) { // $event๋ ์ด๋ฒคํธ ๊ฐ์ฒด์
๋๋ค!
if (event) {
event.preventDefault()
}
alert(msg)
}
}
[3-2] ๋ณตํฉ ์ด๋ฒคํธ ํธ๋ค๋ฌ
์ฌ๋ฌ๊ฐ์ ํจ์๋ฅผ ์คํ์ํค๊ณ ์ถ์ ๋, ์๋์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
<h1 @click="a(); b(); c()">Hello Vue</h1>
<!-- Vue2 -->
<h1 @click="a(), b(), c()">Hello Vue</h1>
<!-- Vue3 -->
[3-3] ์ด๋ฒคํธ ์์์ด
<!-- ํด๋ฆญ ์ด๋ฒคํธ ์ ํ ์ค๋จ -->
<a @click.stop="doThis"></a>
<!-- ์ ์ถ ์ด๋ฒคํธ๊ฐ ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํ์ง ์์ต๋๋ค. -->
<form @submit.prevent="onSubmit"></form>
<!-- ์์ ์๋ ์ฒด์ด๋์ด ๊ฐ๋ฅํฉ๋๋ค. -->
<a @click.stop.prevent="doThat"></a>
<!-- ๋จ์ํ ์์์ด๋ง ์ฌ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค. -->
<form @submit.prevent></form>
<!-- ์บก์ฒ ๋ชจ๋๋ฅผ ์ฌ์ฉํ ๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.-->
<!--์ฆ, ๋ด๋ถ ์๋ฆฌ๋จผํธ๋ฅผ ๋์์ผ๋ก ํ๋ ์ด๋ฒคํธ๊ฐ ํด๋น ์๋ฆฌ๋จผํธ์์ ์ฒ๋ฆฌ๋๊ธฐ ์ ์ ์ฌ๊ธฐ์ ์ฒ๋ฆฌํฉ๋๋ค. -->
<div @click.capture="doThis">...</div>
<!-- event.target์ด ์๋ฆฌ๋จผํธ ์์ฒด์ธ ๊ฒฝ์ฐ์๋ง ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.-->
<!-- ์์ ์๋ฆฌ๋จผํธ์์๋ ์ฒ๋ฆฌ๋์ง ์์ต๋๋ค.-->
<div @click.self="doThat">...</div>
[1] prevent
ํด๋น JavaScript ์ฝ๋๋ฅผ ์งง๊ฒ prevent
์์์ด ํ๋๋ก ๋์ฒดํ ์ ์์ต๋๋ค.
window.addEventListener("load", () => {
const aEL = document.querySelector("a");
aEL.addEventListener("click", (e) => {
e.preventDefault();
});
});
<a href="https://google.com" target="_blank" @click.prevent>Google</a>
๋ง์ฝ @์ด๋ฒคํธ.prevent=โ๋ฉ์๋ ์ด๋ฆโ
์ ์
๋ ฅํ๋ฉด, ๊ธฐ๋ณธ ๋์์ด ์ ์ด๋๊ณ ํด๋น ๋ฉ์๋๊ฐ ์คํ๋ฉ๋๋ค.
[2] stop
stop
์์์ด๋ก ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
<div id="app">
<div class="parent" @click="log">
<div class="child" @click.stop="log"></div>
<!-- ์์ ์์๋ก์ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง์ ๋ฐฉ์งํฉ๋๋ค. -->
</div>
</div>
[3] capture
์ด๋ฒคํธ ์บก์ณ๋ง์ capture
์์์ด๋ฅผ ํตํด ๊ตฌํํ ์ ์์ต๋๋ค.
window.addEventListener(
"click",
() => {
console.log("window");
},
{ capture: true }
);
<div class="parent" @click.capture="log">
<!-- ์ด๋ฒคํธ ์บก์ณ -->
<div class="child" @click.stop="log"></div>
</div>
[4] self
์ด๋ฒคํธ ๋ฐ์ ์, ์ด๋ฒคํธ ๊ฐ์ฒด์ currentTarget๊ณผ target์ ๋ค๋ฅธ ์๋ฏธ๋ฅผ ๊ฐ์ง๋๋ค.
target์ ํ์ฌ ํด๋ฆญํ ๋ถ๋ถ์ ๋งํ๋ฉฐ currentTarget์ ์ด๋ฒคํธ๊ฐ ์ฐ๊ฒฐ์ด ๋์ด์๋ ๋ถ๋ถ์ ๋งํฉ๋๋ค.
self
์์์ด๋ currentTarget๊ณผ target์ด ๊ฐ์ ์์์ผ๋๋ง ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํต๋๋ค.
<div class="parent" @click.self="log">
<div class="child"></div>
</div>
[5] passive
passive
์์์ด๋ ํ๋ฉด์ ์์ง์๊ณผ ๋ฉ์๋ ๋ด๋ถ์ ์ฒ๋ฆฌ๋ฅผ ๋ถ๋ฆฌ์ํต๋๋ค.
window.addEventListener(
"click",
() => {
console.log("window");
},
{ passive: true }
);
<div class="parent" @wheel.passive="log">
<div v-for="n in 15" class="child">{{ n }}</div>
</div>
[3-4] ํค ์์์ด
ํค๋ณด๋ ์ด๋ฒคํธ์์ ํค ์ฝ๋๋ฅผ ํ์ธํด์ผ ํ ๋, ํค ์์์ด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํค๋ณด๋์์ ์ ๊ณตํ๋ ํค์ ์ด๋ฆ์ ์ผ๋ฐฅ ์ผ์ด์ค๋ก ๋ณํํ์ฌ ์์์ด๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
<input @keyup.page-down="onPageDown" /> <input @keyup.arrow-down="log" />
ํค ์์์ด๋ ์ฒด์ด๋ ํํ๋ก ์์ฑํ ์ ์์ต๋๋ค.
<input @keyup.alt.enter="clear" />
<!-- ์ํธ์ ์ํฐ๋ฅผ ๋์์ ํด๋ฆญ ์ ์ด๋ฒคํธ -->
๊ธฐ๋ณธ์ ์ผ๋ก ํค๋ณด๋ ์ด๋ฒคํธ๋ ๋์์ ๋๋ฅธ ํค๋ค ์ค์ ํด๋น ํค๊ฐ ํฌํจ๋์ด ์๋์ง์ ์ฌ๋ถ๋ง ์ฒดํฌํฉ๋๋ค.
ํด๋น ํค๋ง ๋๋ ธ๋์ง ์ฒดํฌํ๊ธฐ ์ํด์๋ exact
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
<input @keyup.arrow-down.exact="log" />
<!-- ํค๋ณด๋ ์๋ ํค๋ง ๋๋ ์ ๋ ์ด๋ฒคํธ๊ฐ ๋์ํฉ๋๋ค. -->
[4] ํผ ์ ๋ ฅ ๋ฐ์ธ๋ฉ
v-model
๋๋ ํฐ๋ธ๋ฅผ ์ฌ์ฉํด์ ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์์ฑํ ์ ์์ต๋๋ค.
- ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ: ๋ฐ์ดํฐ๊ฐ ํ์ชฝ์ผ๋ก ์ ๋ฌ
- ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ: ๋ฐ์ดํฐ๊ฐ ์๋ฐฉํฅ์ผ๋ก ์ํธ์์ฉ
๋จ v-model
์ ํ๊ธ์ ๋ํด์๋ ์ฝ๊ฐ ๋ค๋ฅด๊ฒ ๋์ํฉ๋๋ค.
ํ ๊ธ์๊ฐ ์์ฑ์ด ๋์ด์ผ๋ง ๋ฐ์์ด ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด๋ด๋, :value
์ @input
์์ฑ์ ์ฌ์ฉํ์ฌ ์์ฑ์ ํ ์ ์์ต๋๋ค.
<input :value="msg" @input="msg = $event.target.value" />
[4-1] ์์์ด
[1] lazy
v-model์ ๊ฐ ์ด๋ฒคํธ ํ ์ ๋ ฅ๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋๊ธฐํํฉ๋๋ค.
lazy ์์์ด๋ฅผ ์ถ๊ฐํ์ฌ change ์ด๋ฒคํธ ์ดํ์ ๋๊ธฐํ๊ฐ ๋๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
<input v-model.lazy="msg" />
[2] number
์ฌ์ฉ์ ์ ๋ ฅ์ ์๋์ผ๋ก ์ซ์๋ก ํ๋ณํ์ํฌ ์ ์์ต๋๋ค.
<input v-model.number="msg" />
[3] trim
์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋ด์ฉ์์ ์๋์ผ๋ก ์๋ค ๊ณต๋ฐฑ์ ์ ๊ฑฐํด์ค๋๋ค.
<input v-model.trim="msg" />
๋๊ธ๋จ๊ธฐ๊ธฐ