VUE

[VUE] ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ / vue transition ์ ์šฉํ•˜๊ธฐ

์˜ˆ๊ธ€ 2024. 4. 19. 16:46

๐Ÿš€ 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" ์ ์Œ