๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[๊ฐœ๋ฐœ] Practice/Vue.js

[Vue.js] Vue ์—์„œ UI ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ ์ฃผ๊ธฐ

by Connecting-the-dots 2022. 4. 3.
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ’ก ์‹ค์Šต ํฌ์ธํŠธ!

  • ์ด๋ฒˆ์—๋Š” Vue ์—์„œ ์ œ๊ณตํ•˜๋Š” transition ์„ ์ด์šฉํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ์ฃผ๋Š” ๋ฐฉ๋ฒ•์„ ํฌํ•จํ•˜์—ฌ ์ด 2๊ฐ€์ง€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๋Š” ๋ฐฉ๋ฒ•์„ ๊ณต๋ถ€ํ•ด๋ณด์•˜๋‹ค.
  • ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ค„ ๋•Œ๋Š” ํˆฌ๋ช…๋„๋งŒ 0์—์„œ 1๋กœ ๋ฐ”๋€Œ๋„๋ก ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ค˜๋ณด์•˜๊ณ , transition ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ชจ๋‹ฌ์ฐฝ์ด ์œ„์—์„œ ๋‚ด๋ ค์˜ค๊ณ , ๋‹ซ์„ ๋•Œ์—๋Š” ์•„๋ž˜๋กœ ์‚ฌ๋ผ์ง€๋„๋ก ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ค˜๋ณด์•˜๋‹ค.
  • ๋‚˜๋Š” ๋ถ„๋ช…ํžˆ transition ์„ ์ด์šฉํ•ด ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ถ”๊ฐ€ํ•œ ๊ฒƒ๋ฟ์ธ๋ฐ, ๊ธฐ์กด์— ์ž˜ ์ž‘๋™ํ•˜๋˜ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์ด ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ  ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์„œ.. ๊ตฌ๊ธ€๋งํ•˜๊ณ  ์—๋Ÿฌ๋ฅผ ์ˆ˜์ •ํ•˜๋Š๋ผ ํ•œ์ฐธ ๊ฑธ๋ ธ๋‹ค.
  • ๊ทธ๋ž˜์„œ ๋ชจ๋“  ์ˆ˜์ •์„ ๋งˆ์นœ ํ›„์— ์—ฌ๊ธฐ์ €๊ธฐ ๋ˆŒ๋Ÿฌ๋ณด๋ฉด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธ๊นŒ์ง€ ํ•œ ํ›„์—์•ผ ๋งˆ์Œ์„ ๋†“์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๐Ÿ’œ ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—

  • UI ๊ฐ€ ๋“ฑ์žฅ ํ˜น์€ ํ‡ด์žฅํ•  ๋•Œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ๋‹ค.
  • ์ด ๋•Œ, ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๋Š” ๋ฐ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.
    • JavaScript ์—์„œ๋„ ์ž์ฃผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ, ํด๋ž˜์Šค์— CSS ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๋งŒ๋“  ํ›„์— ํ•ด๋‹น class ๋ฅผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๊ฐ€ ํ•„์š”ํ•œ UI ์— ๋–ผ์—ˆ๋‹ค ๋ถ™์˜€๋‹ค ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ CSS ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ฃผ๋Š” ๋ฐฉ๋ฒ•
      (๋ฌผ๋ก  ๊ณผ์ •์€ ๋™์ผํ•˜๋‚˜ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ์•ฝ๊ฐ„ ๋‹ค๋ฅด๊ธด ํ•˜๋‹ค.)
    • Vue ๊ฐ€ ์ œ๊ณตํ•˜๋Š” <transition> ์— name ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•ด๋‹น name ์„ ๊ฐ€์ง€๊ณ  CSS ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๋งŒ๋“ค๊ณ , ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๊ฐ€ ํ•„์š”ํ•œ UI ๋ฅผ <transition></transition> ์œผ๋กœ ๊ฐ์‹ธ๋Š” ๋ฐฉ๋ฒ•

๐Ÿ’œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ• ์‚ฌ์šฉํ•˜๊ธฐ

<div class="start" :class="{ end : openModal }">
    <Modal @closeModal="openModal = close($event)" :openModal="openModal" :clickedRoom="clickedRoom" :rooms="rooms"/>
</div>
  • ๋จผ์ €, ๊ธฐ์กด์˜ Modal Component ์— ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด start ๋ผ๋Š” class ๋ฅผ ๊ฐ€์ง„ div ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ฃผ์—ˆ๋‹ค.
  • ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘ ์ „/ํ›„๋กœ ์„ค์ •ํ•  class ๋ช…์€ ์ด ๋•Œ ๋ฏธ๋ฆฌ ์ƒ๊ฐํ•ด์ฃผ๋Š” ๊ฒŒ ์ข‹๋‹ค.

 

.start {
	opacity: 0;	
	transition: all 1s;
}

.end {
	opacity: 1;
}
  • ๊ทธ๋ฆฌ๊ณ  start ๋ผ๋Š” ํƒœ๊ทธ์— css ๋กœ ์‹œ์ž‘ ์ „ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋””์ž์ธํ•˜๊ณ , end ๋ผ๋Š” ํƒœ๊ทธ์— css ๋กœ ๋™์ž‘ ํ›„ class ๋ฅผ ๋””์ž์ธ์„ ํ•ด์ฃผ์—ˆ๋‹ค.
  • ์ด๋ฒˆ์—๋Š” ๋‹จ์ˆœํžˆ ํˆฌ๋ช…๋„๋งŒ 0์—์„œ 1๋กœ ๋ฐ”๊พธ์–ด ๋ชจ๋‹ฌ์ฐฝ์ด ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ค˜๋ณด์•˜๋‹ค.
<div class="start" :class="{ end : openModal }"></div>
  • ์ด์ œ ์›ํ•˜๋Š” ์‹œ์ ์— end ๋ผ๋Š” class ๋ฅผ start ๋ผ๋Š” class ๋ฅผ ๊ฐ€์ง„ div ํƒœ๊ทธ์— ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
  • JavaScript ์—์„œ๋Š” ์‚ผํ•ญ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•˜์—ฌ ์กฐ๊ฑด์„ ์ž‘์„ฑํ•ด์ฃผ์—ˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ๋Š” ์กฐ๊ฑด๋ถ€๋กœ class ๋ฅผ ๋ถ€์ฐฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์œ„์™€ ๊ฐ™์ด :class="{ ํด๋ž˜์Šค๋ช… : true }" ์™€ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ๋ฌผ๋ก  true / false ๋ฅผ ์ง์ ‘ ๋ฌธ์ž์—ด๋กœ ์ž…๋ ฅํ•ด์ฃผ์–ด๋„ ๋˜๊ณ , data ๋ณด๊ด€ํ•จ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์ด๋ฆ„๋„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋‚˜์˜ ๊ฒฝ์šฐ, ๋ชจ๋‹ฌ์ฐฝ UI ๊ฐ€ ์—ด๋ ธ์„ ๋•Œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๊ฐ€ ๋ถ€์ฐฉ๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ ๋ชจ๋‹ฌ์ฐฝ์˜ ์—ด๊ณ  ๋‹ซํžŒ ์ƒํƒœ์— ๋”ฐ๋ผ true / false ๊ฐ’์ด ์ €์žฅ๋˜๋Š” openModal ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

๐Ÿ’œ Vue ๊ฐ€ ์ œ๊ณตํ•˜๋Š” transition ์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ ์ฃผ๋Š” ๋ฐฉ๋ฒ• ์‚ฌ์šฉํ•˜๊ธฐ

<transition name="fade">
	<Modal @closeModal="openModal = close($event)" :openModal="openModal" :clickedRoom="clickedRoom" :rooms="rooms"/>
</transition>
  • ๋จผ์ €, ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๊ณ  ์‹ถ์€ UI ๋ฅผ <transition></transition> ์œผ๋กœ ๊ฐ์‹ธ์ค€๋‹ค.
  • ์ด ๋•Œ, <transition> ์— name ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ css ๋ฅผ ๋งŒ๋“ค ๋•Œ class ๋ช…์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ด๋ฆ„์„ ํ•˜๋‚˜ ์ง€์–ด์ค€๋‹ค.

 

/* transition ์„ ํ™œ์šฉํ•œ ์Šคํƒ€์ผ๋ง ๋ฐฉ๋ฒ• */
.์ž‘๋ช…-enter-from { ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™์ž‘ ์ „ ์ƒํƒœ }
.์ž‘๋ช…-enter-active { ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™์ž‘ ์ค‘ ์ƒํƒœ, ๋Œ€๋ถ€๋ถ„ transition ์ด๋Ÿฐ๊ฑฐ }
.์ž‘๋ช…-enter-to { ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™์ž‘ ํ›„ ์ƒํƒœ }


.fade-enter-from {
	opacity: 0;
	transform: translateY(-100vh);
}

.fade-enter-active {
	transition: all 0.5s;
}

.fade-enter-to {
	transform: translateY(0vh);
	opacity: 1;
}

.fade-leave-from {
	transform: translateY(0vh);
	opacity: 1;
}

.fade-leave-active {
	transition: all 0.5s;
}

.fade-leave-to {
	transform: translateY(100vh);
	opacity: 0;
}
  • ์ด์ œ ๋งจ ์œ„์˜ transition ์Šคํƒ€์ผ๋ง ๋ฐฉ๋ฒ•์„ ์ฐธ๊ณ ํ•˜์—ฌ css ์—์„œ ์›ํ•˜๋Š” ๋Œ€๋กœ ์Šคํƒ€์ผ๋ง์„ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. 
  • ํ‡ด์žฅ ์‹œ์—๋„ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด enter ๋Œ€์‹ ์— leave ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
  • ์ด๋ฒˆ์—๋Š” ํ™”๋ฉด ์ƒ๋‹จ์—์„œ ๋ชจ๋‹ฌ์ฐฝ์ด ๋‚ด๋ ค์™”๋‹ค๊ฐ€, ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์ด๋‚˜ ๊ฒ€์€ ๋ฐฐ๊ฒฝ์„ ๋ˆ„๋ฅด๋ฉด ๋ชจ๋‹ฌ์ฐฝ์ด ํ™”๋ฉด ํ•˜๋‹จ ๋ฐฉํ–ฅ์œผ๋กœ ์‚ฌ๋ผ์ง€๋„๋ก ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ค˜๋ณด์•˜๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•