๐ vue Transition
1. Transition
- ์๋ฆฌ๋จผํธ๋ ์ปดํฌ๋ํธ๊ฐ ๋์ ๋ค์ด๊ฐ ๋์ ๋๊ฐ ๋ ์ ๋๋ฉ์ด์ ์ ์ ์ฉ
- ๋ด์ฅ๋ ์ปดํฌ๋ํธ. ๊ทธ๋์ ๋ฑ๋กํ ํ์์์ด ๋ชจ๋ ์ปดํฌ๋ํธ์ ํ ํ๋ฆฟ์์ ์ฌ์ฉํ ์ ์์
- v-if ๋ฅผ ํตํ ์กฐ๊ฑด์ ์ธ ๋ ๋๋ง
- v-show ๋ฅผ ํตํ ์กฐ๊ฑด์ ์ธ ๋์คํ๋ ์ด
- ์คํ์ ์๋ฆฌ๋จผํธ์ธ <component>๋ฅผ ํตํด ๋์ ์ธ ์ปดํฌ๋ํธ ํ ๊ธ๋ง
2. TransitionGroup
- list์ ๊ฐ์ด ์ฌ๋ฌ ๊ฐ์ ํ๊ทธ๊ฐ ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํ Transition ์ปดํฌ๋ํธ
- ๊ฐ์ธ๋ ํ๊ทธ๊ฐ ์์ด v-for ๋ฑ์ ์ด์ฉํด ์ฌ๋ฌ ๊ฐ ํ๊ทธ๊ฐ ๋ค์ด๊ฐ์ผํจ. ๋์ tag ๋ผ๋ ์์ฑ์ ํตํด ๊ฐ์(wrap) ํ๊ทธ๋ฅผ ์ง์ ํ ์ ์์
- ๋ฆฌ์คํธ์ ํ๊ทธ๋ค์ ๊ฐ์ ๋ํ๋๊ฑฐ๋ ์ฌ๋ผ์ง๊ณ ์์๋ง ๋ฐ๋๊ธฐ ๋๋ฌธ์, ์๋ก ์ํฅ์ ์ฃผ์ง ์์. ๋ฐ๋ผ์ transition mode(out-in, in-out)๊ฐ ์์.
- ๊ฐ ํ๊ทธ๋ค์ ๋ฐ๋์ ๊ณ ์ ํ key ์์ฑ ๊ฐ์ ๊ฐ์ง๊ณ ์์ด์ผ ํจ.
- v-xxx์ ๊ฐ์ ํด๋์ค๋ ๊ทธ๊ฑธ ๊ฐ์ธ๋ ์ปจํ ์ด๋(container)๊ฐ ์๋ ํ๊ทธ ๊ฐ๊ฐ์ ๋ค์ด๊ฐ.
- ๋ง์ฝ ์ปดํฌ๋ํธ์ template ์์ฑ์ ์ฌ์ฉํ๋ค๋ฉด <TransitionGroup>์ด ์๋ <transition-group>์ผ๋ก ์ฌ์ฉํด์ผ ํจ.
1. HomeView.vue
<template>
<div class="home" ref="parent">
...
<!-- ์นดํ
๊ณ ๋ฆฌ -->
<Category :categoryType="categoryType" @setCategory="setCategory" />
<!-- ์ํ ๋ฆฌ์คํธ -->
<MainList :categoryType="categoryType" />
...
</div>
</template>
<script>
export default {
components: {
...
},
data() {
return {
categoryType: "all",
};
},
methods: {
setCategory(value) {
this.categoryType = value;
},
},
};
</script>
์นดํ ๊ณ ๋ฆฌ์ ์ํ ๋ฆฌ์คํธ ์ปดํฌ๋ํธ์ ๋ฐ์ดํฐ, ํจ์๋ฅผ ์ ๋ฌํด์ผ ํ๋ฏ๋ก ๊ทธ๋ค์ ์์ ์ปดํฌ๋ํธ์ธ HomeView.vue์ ๋ณ์, ํจ์ ์์ฑ
2. Category.vue
<template>
<!-- isScrollDown์ด true์ผ ๋ categoryTop ํด๋์ค ์ ์ฉ -->
<nav class="categoryWrap" :class="{ categoryTop: isScrollDown }">
<ul>
<li @click="$emit('setCategory', 'all')">์ ์ฒด</li>
<li @click="$emit('setCategory', 'outwear')">์์ฐํฐ</li>
<li @click="$emit('setCategory', 'top')">์์</li>
<li @click="$emit('setCategory', 'footwear')">์ ๋ฐ</li>
<li @click="$emit('setCategory', 'bags')">๊ฐ๋ฐฉ</li>
<li @click="$emit('setCategory', 'stuff')">์กํ</li>
</ul>
</nav>
</template>
<script>
export default {
name: "Category",
props: ["categoryType"],
data() {
return {
nowScrollY: 0,
isScrollDown: false,
navTop: 0,
};
},
methods: {
...
},
...
};
</script>
<style lang="scss" scoped>
...
</style>
ํด๋น li ํด๋ฆญํ๋ฉด $emit('setCategory')์ ๊ทธ ์นดํ ๊ณ ๋ฆฌ์ ๋ง๋ value ๋ถ์ฌ
3. MainList.vue
<template>
<div>
<h2>์ํ ๋ชฉ๋ก</h2>
<List :data="product" :categoryType="categoryType" />
</div>
</template>
<script>
export default {
components: { List },
props: ["categoryType"],
data() {
return {
product,
};
},
};
</script>
<style lang="scss" scoped>
...
</style>
4. List.vue
<template>
<transition-group tag="ul" class="listWrap">
<template v-for="item in data">
<div
v-if="categoryType === 'all' || item.category === categoryType"
:key="item.id"
>
<MainItem :item="item" />
</div>
</template>
</transition-group>
</template>
<script>
import MainItem from "@/components/Molecules/MainItem.vue";
export default {
props: ["data", "categoryType"],
components: { MainItem },
data() {
return {};
},
};
</script>
<style lang="scss" scoped>
.listWrap {
padding: 1.5rem;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}
/* ํธ๋์ง์
์ ์ฉ ์คํ์ผ */
.v-enter-active,
.v-leave-active,
.v-move {
transition: opacity 1s, transform 1s;
}
.v-leave-active {
position: absolute;
}
.v-enter {
opacity: 0;
transform: translateY(-20px);
}
.v-leave-to {
opacity: 0;
transform: translateY(20px);
}
...
</style>
(1) ์นดํ ๊ณ ๋ฆฌ์ ๋ง๋ ๋ฐ์ดํฐ๋ง ๋ณด์ฌ์ค
(2) ์ฌ๋ฌ ๊ฐ์ ํ๊ทธ๊ฐ ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ์ด๋ฏ๋ก transition-group ์ ์ฉ
(3) <template> cannot be keyed. place the key on real elements instead. ๋ผ๋ ์๋ฌ๊ฐ ๋ ๋ฌ template ํ์ ํ๊ทธ์ธ div์ :key="item.id" ์ ์