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

[Vue.js] Composition API ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

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

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

  • ์˜ค๋Š˜ ๊ณต๋ถ€ํ•œ Composition API ๋ฅผ ์‚ฌ์šฉํ•ด์„œ MyPage ์— ํŒ”๋กœ์›Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉํ•ด์ฃผ์—ˆ๋‹ค.

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

  • vue ํŒŒ์ผ์˜ ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๋ฉด ํŠน์ • ๋ฐ์ดํ„ฐ์™€ ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ์„ ์ฐพ๊ธฐ ์œ„ํ•ด ์—ฌ๊ธฐ์ €๊ธฐ ํ™•์ธ์„ ํ•ด์•ผํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.
  • ์ด๊ฒŒ ์‹ซ๋‹ค๋ฉด, Vue 3 ๋ฒ„์ „๋ถ€ํ„ฐ ์ œ๊ณตํ•˜๋Š” Composition API ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
  • Composition API ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด computed, methods, watch, data() ์ด๋Ÿฐ ๊ฑธ๋กœ ํŒŒ์ผ์„ ์ชผ๊ฐœ์ง€ ์•Š๊ณ  ๊ด€๋ จ ๊ธฐ๋Šฅ๋“ค์„ ํ•œ ๊ณณ์— ๋ชจ์•„ ์ญ‰ ์ฝ”๋“œ๋ฅผ ์งค ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค๋งŒ, Composition API ๋ฐฉ์‹์€ ๊ธฐ์กด์˜ Options API ๋ฐฉ์‹๋ณด๋‹ค๋Š” ๋ฌธ๋ฒ•์ด ๊ท€์ฐฎ์„ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ’œ ํŒ”๋กœ์›Œ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ

๐Ÿค MyPage.vue ๋งŒ๋“ค๊ธฐ

<template>
<div class="mypage">
  <h4 class="followers">ํŒ”๋กœ์›Œ</h4>
  <input class="search" placeholder="๐Ÿ”" />
  <div class="post-header">
    <div class="profile"></div>
    <span class="profile-name">์‚ฌ์šฉ์ž๋ช…</span>
  </div>
</div>
</template>

<script>
export default {
  name: "MyPage",
  data() {
    return {};
  },
};
</script>

<style>
.followers,
.mypage {
  text-align: center;
  padding: 0 10px;
}

.search {
  width: 80%;
  margin-bottom: 20px;
  padding: 10px;
  font-size: 16px;
  font-weight: bold;
}
</style>
  • ์ผ๋‹จ ํŒ”๋กœ์›Œ๋ฅผ ๋ณด์—ฌ์ค„ MyPage ๋Š” ์œ„์™€ ๊ฐ™์ด ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

 

<div v-if="step === 3">
  <MyPage />
</div>
  • ๊ทธ๋ฆฌ๊ณ  Container.vue ํŒŒ์ผ์— MyPage Component ๋ฅผ import ๋ฐ ๋“ฑ๋กํ•œ ํ›„์— step ์ด 3 ์ผ ๋•Œ ๋ณด์ด๋„๋ก ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

 

<ul class="header-button-right">
  <li @click="step = 3" v-if="step === 0">My Page</li>
  <li @click="step++" v-if="step === 1">Next</li>
  <li @click="publish" v-if="step === 2">๋ฐœํ–‰</li>
</ul>
  • App.vue ์—์„œ๋Š” ๋ฉ”์ธ ํŽ˜์ด์ง€, ์ฆ‰ step ์ด 0 ์ผ ๋•Œ ์šฐ์ธก ์ƒ๋‹จ์— MyPage ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.
  • step state ์˜ ์ˆซ์ž์— ๋”ฐ๋ผ ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€๊ฐ€ ๋ฐ”๋€Œ๊ณ  ๊ทธ์— ๋งž๋Š” ๋ฒ„ํŠผ๋“ค์ด ๊ฐ ํŽ˜์ด์ง€์˜ ์šฐ์ธก ์ƒ๋‹จ์— ์ƒ๊ธฐ๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.

๐Ÿค followers.json ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ

[
  { "id" : 0, "name" : "_Limvely", "image" : "https://placeimg.com/200/200/animals/grayscale" },
  { "id" : 1, "name" : "salmon_X", "image" : "https://placeimg.com/200/250/people" },
  { "id" : 2, "name" : "360noscope", "image" : "https://placeimg.com/200/250/animals" },
  { "id" : 3, "name" : "Jeony_1", "image" : "https://placeimg.com/200/200/people/sepia" },
  { "id" : 4, "name" : "mihyeon", "image" : "https://placeimg.com/200/200/tech" }   
]
  • ajax ์š”์ฒญ์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ํŒ”๋กœ์›Œ ํ”„๋กœํ•„ ๋ฐ์ดํ„ฐ๋“ค์„ ๋‹ด์€ followers.json ํŒŒ์ผ์„ public ํด๋”์— ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

๐Ÿค Composition API ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ๋งŒ๋“ค๊ธฐ

import { ref } from 'vue'

export default {
  name : 'MyPage',
  setup(){
    let followers = ref([]);
    
    return { followers }
  },
}
  • ์ด์ œ follower.json ์œผ๋กœ๋ถ€ํ„ฐ ๋ถˆ๋Ÿฌ์˜ฌ ๋ฐ์ดํ„ฐ๋“ค์˜ ์ด๋ฆ„์„ ์ €์žฅํ•  ๊ณต๊ฐ„์ด ํ•„์š”ํ•˜๋‹ค.
  • ์ด์ „(Options API)์—๋Š” data ๋ณด๊ด€ํ•จ์— ํ•ญ๋ชฉ์„ ๋งŒ๋“ค์–ด ์ €์žฅํ–ˆ์ง€๋งŒ, Composition API ์—์„œ๋Š” setup() ์ด๋ผ๋Š” hook ๊ฐ™์€ ๊ฑธ ๋งŒ๋“ค์–ด ๊ทธ ์•ˆ์— ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.
  • ์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ๋ฉด followers: [] ์ด๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“  ๊ฒƒ๊ณผ ๋™์ผํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • ref() ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ import ํ•ด์˜จ ํ›„์—, let ๋ฐ์ดํ„ฐ์ด๋ฆ„ = ref(๋ฐ์ดํ„ฐ) ์˜ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด์ฃผ์–ด์•ผ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์žฌ๋ Œ๋”๋ง์ด ๋œ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์—๋Š” ํ•ญ์ƒ return { } ์•ˆ์— ๋ฐ์ดํ„ฐ์ด๋ฆ„์„ ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผ <template></template> ์—์„œ {{ ๋ฐ์ดํ„ฐ์ด๋ฆ„ }} ์˜ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. 

๐Ÿค Ajax ์š”์ฒญํ•˜๊ธฐ ๋ฐ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝํ•˜๊ธฐ

import { ref } from 'vue'
import axios from 'axios'

export default {
  name : 'MyPage',
  setup(){
    let followers = ref([]);
    
    axios.get('/followers.json').then((result)=>{
      followers.value = result.data
    })
    
    return { followers }
  },
}
  • Composition API ๋„ ajax ๋ฅผ ์š”์ฒญํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋™์ผํ•œ๋ฐ, ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ์‹์€ ์ด์ „๊ณผ ์ข€ ๋‹ค๋ฅด๋‹ค.
  • ๋จผ์ € axios ๋ฅผ import ํ•ด์ค€ ๋‹ค์Œ์— GET ์š”์ฒญ์œผ๋กœ ์ด์ „์— ์ €์žฅํ•œ followers.json ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜จ๋‹ค.
  • followers.json ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋Š” result ์— ์ €์žฅ์ด ๋˜๊ณ , ์ด๋ฅผ ์ถœ๋ ฅํ•ด๋ณด๋ฉด result.data ์•ˆ์— [{ }, { }, { }...] ์™€ ๊ฐ™์€ array ์ž๋ฃŒํ˜•์ด ์ €์žฅ๋˜์–ด์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ result.data ๋ฅผ followers ์— ์ €์žฅํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, followers = result.data ๊ฐ€ ์•„๋‹ˆ๋ผ followers.value = result.data ๋ผ๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๐Ÿค Lifecycle hook ์‚ฌ์šฉํ•˜๊ธฐ

import { onMounted, ref } from "vue";
import axios from "axios";

export default {
  name: "MyPage",
  setup() {
    let followers = ref([]);

    onMounted(() => {
      axios.get("/followers.json").then((result) => {
        followers.value = result.data;
      });
    });
    return { followers };
  },
};
  • Component ๊ฐ€ ๋ถ€์ฐฉ๋  ๋•Œ๋‚˜ ์—…๋ฐ์ดํŠธ๋  ๋•Œ ๋ฌด์–ธ๊ฐ€๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด created(), mounted(), beforeUpdate() ์ด๋Ÿฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค๋งŒ Composition API ์—์„œ๋Š” ํ•จ์ˆ˜๋ช…์ด ์•ฝ๊ฐ„ ๋‹ค๋ฅด๋‹ค.
    • onMounted() ์ด๋Ÿฐ hook ์„ import ํ•œ๋‹ค.
      (์ด์ „์— Lifecycle hook ์œผ๋กœ ์‚ฌ์šฉํ•˜๋˜ ํ•จ์ˆ˜๋ช… ์•ž์— on ์„ ๋ถ™์—ฌ์ฃผ์–ด์•ผ ํ•œ๋‹ค. ๋‹ค๋งŒ, created() ๋Š” on ์„ ๋ถ™์ด์ง€๋„ ์•Š๊ฑฐ๋‹ˆ์™€ setup() ์ž์ฒด๊ฐ€ created() ์™€ ๋งค์šฐ ์œ ์‚ฌํ•˜๋ฏ€๋กœ ์‚ฌ์šฉํ•  ์ผ๋„ ๊ฑฐ์˜ ์—†๋‹ค.)
    • onMounted(()=>{ Mount ์ดํ›„์— ์‹คํ–‰ํ•  ์ฝ”๋“œ }) ์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
      (์œ„ ์ฝ”๋“œ๋Š” mount ํ›„์— ajax ์š”์ฒญ์„ ์‹คํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค.)

๐Ÿค followers.json ํŒŒ์ผ ๋ฐ์ดํ„ฐ๋กœ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ

  <div class="mypage">
    <h4 class="followers">ํŒ”๋กœ์›Œ</h4>
    <input
      class="search"
      placeholder="๐Ÿ”"
    />
    <div class="post-header" v-for="(follower, i) in followers" :key="i">
      <div
        class="profile"
        :style="`background-image: url(${follower.image})`"
      ></div>
      <span class="profile-name">{{ follower.name }}</span>
    </div>
  </div>
  • ajax ์š”์ฒญ์„ ํ†ตํ•ด followers.json ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€์„œ, ๋ฐ˜๋ณต๋ฌธ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ์„ ํ•ด์ฃผ์—ˆ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•