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

[Vue.js] ์ธ์Šคํƒ€๊ทธ๋žจ ํ•„ํ„ฐ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

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

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

  • ์ž‘์€ ์ด๋ฏธ์ง€๋“ค์— ํ•„ํ„ฐ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•ด์„œ ๋ณด์—ฌ์ฃผ๋Š” ๊ฑด ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ์ž‘์€ ์ด๋ฏธ์ง€๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ํฐ ์ด๋ฏธ์ง€์— ํ•„ํ„ฐ๊ฐ€ ์ž…ํ˜€์ง€๋Š” ๊ธฐ๋Šฅ์€ ์•ˆ ๋งŒ๋“ค์–ด์„œ(์บก์ฒ˜ํ•˜๋‹ค๊ฐ€ ์ƒ๊ฐ๋‚ฌ๋‹ค...) ์กฐ๋งŒ๊ฐ„ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ๊ฒ ๋‹ค.

๐Ÿ’œ ํ•„ํ„ฐ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

  • ์‚ฌ์ง„ ์—…๋กœ๋“œ ํŽ˜์ด์ง€(ํ•„ํ„ฐ ์„ ํƒ ํŽ˜์ด์ง€)๋ฅผ ๋ณด๋ฉด ํ•˜๋‹จ์— ์ž‘์€ ๋ฐ•์Šค๋“ค์ด ์žˆ๋Š”๋ฐ ์ด ๊ฐ ๋ฐ•์Šค๋“ค์„ FilterBox Component ๋กœ ๋ฐ”๊พธ์–ด์ค„ ๊ฒƒ์ด๋‹ค.

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

// ์ „์ฒด ์ฝ”๋“œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
// ์ „์ฒด ์ฝ”๋“œ์˜ ๋‚ด์šฉ์ด ๊ธธ์–ด css ๋ถ€๋ถ„์€ ์ œ์™ธํ–ˆ๋‹ค.

<template>
  <div class="filter-item" :style="`background-image: url(${imgUrl})`">
  </div>
</template>

<script>
export default {
  name: "FilterBox",
  data() {
    return {};
  },
  props: {
    imgUrl: String,
  },
};
</script>

<style>
.filter-item {
  width: 100px;
  height: 100px;
  margin: 10px 10px 10px auto;
  padding: 8px;
  display: inline-block;
  color: white;
  background-size: cover;
  background-position: center;
}
</style>
  • FilterBox Component ๋กœ ์ž‘์€ ๋ฐ•์Šค๋“ค์„ ์ฑ„์šฐ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ์„  FilterBox Component ๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
  • ๋”ฐ๋ผ์„œ, FilterBox.vue ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ ์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์—ˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์ž‘์€ ๋ฐ•์Šค๋“ค์€ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€๊ฐ€ ์ฑ„์›Œ์ง„ ์ƒํƒœ์—์„œ ํ•„ํ„ฐ๊ฐ€ ์ž…ํ˜€์ง€๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, ๊ฐ ๋ฐ•์Šค์˜ background-image ์†์„ฑ์œผ๋กœ App.vue ๋กœ๋ถ€ํ„ฐ props ๋กœ ๋ฐ›์•„์˜จ imgUrl ์„ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

๐Ÿค Container.vue ์ˆ˜์ •ํ•˜๊ธฐ

// ์ „์ฒด ์ฝ”๋“œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
// ์ „์ฒด ์ฝ”๋“œ์˜ ๋‚ด์šฉ์ด ๊ธธ์–ด css ๋ถ€๋ถ„์€ ์ œ์™ธํ–ˆ๋‹ค.

<template>
  <div>
    <div v-if="step === 0">
      <Post :post="post" v-for="(post, i) in posts" :key="i" />
    </div>

    <!-- ํ•„ํ„ฐ์„ ํƒํŽ˜์ด์ง€ -->
    <div v-if="step === 1">
      <div
        class="upload-image"
        :style="{ backgroundImage: `url(${imgUrl})` }"
      ></div>
      <div class="filters">
        <FilterBox
          :class="filter"
          :imgUrl="imgUrl"
          v-for="(filter, i) in filters"
          :key="i"
        ></FilterBox>
      </div>
    </div>

    <!-- ๊ธ€์ž‘์„ฑํŽ˜์ด์ง€ -->
    <div v-if="step === 2">
      <div
        class="upload-image"
        :style="{ backgroundImage: `url(${imgUrl})` }"
      ></div>
      <div class="write">
        <textarea
          class="write-box"
          @input="$emit('content', $event.target.value)"
          placeholder="๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”!"
        ></textarea>
      </div>
    </div>
  </div>
</template>

<script>
import Post from "./Post.vue";
import FilterBox from "./FilterBox.vue";
export default {
  name: "Container",
  data() {
    return {
      filters: [
        "aden",
        "_1977",
        "brannan",
        "brooklyn",
        "clarendon",
        "earlybird",
        "gingham",
        "hudson",
        "inkwell",
        "kelvin",
        "lark",
        "lofi",
        "maven",
        "mayfair",
        "moon",
        "nashville",
        "perpetua",
        "reyes",
        "rise",
        "slumber",
        "stinson",
        "toaster",
        "valencia",
        "walden",
        "willow",
        "xpro2",
      ],
    };
  },
  components: {
    Post,
    FilterBox,
  },
  props: {
    posts: Array,
    step: Number,
    imgUrl: String,
  },
};
</script>

<style>
</style>
  • Container.vue ์—์„œ FilterBox Component ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์šฐ์„  FilterBox ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ FilterBox Component ๋ฅผ import ํ•ด์ฃผ๊ณ , components ์—๋„ ๋“ฑ๋กํ•ด์ฃผ์—ˆ๋‹ค.

 

[ "aden", "_1977", "brannan", "brooklyn", "clarendon", "earlybird", "gingham", "hudson", 
"inkwell", "kelvin", "lark", "lofi", "maven", "mayfair", "moon", "nashville", "perpetua", 
"reyes", "rise", "slumber", "stinson", "toaster", "valencia", "walden", "willow", "xpro2"]
  • ๊ทธ๋Ÿฌ๊ณ  ๋‚˜์„œ, data ๋ณด๊ด€ํ•จ์— filters ๋ผ๋Š” ํ•ญ๋ชฉ์„ ๋งŒ๋“ค์–ด์„œ ์œ„์˜ ํ•„ํ„ฐ๋“ค ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์ฃผ์—ˆ๋‹ค.

 

  <div class="filters">
    <FilterBox
      :class="filter"
      :imgUrl="imgUrl"
      v-for="(filter, i) in filters"
      :key="i"
    ></FilterBox>
  </div>
  • ์ด์ œ filters ์— ๋‹ด๊ธด ๋ฐ์ดํ„ฐ๋งŒํผ ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ ค์„œ, ์‚ฌ์ง„ ์—…๋กœ๋“œ ํŽ˜์ด์ง€ ํ•˜๋‹จ์˜ ์ž‘์€ ์ด๋ฏธ์ง€๋“ค์— ํ•„ํ„ฐ๋ฅผ ์”Œ์›Œ์ฃผ๋ฉด ๋œ๋‹ค.
  • ์ด ๋•Œ, ์ค‘์š”ํ•œ ๊ฒƒ์€ ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ฆฐ๋‹ค๊ณ  ํ•ด์„œ ์‹ค์ œ๋กœ ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ณ  ๊ทธ๋ƒฅ filters ์˜ ๊ธธ์ด๋งŒํผ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€์™€ ๋˜‘๊ฐ™์ด ์ƒ๊ธด ์ž‘์€ ์ด๋ฏธ์ง€๋งŒ ์ƒ๊ธด๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ์‹ค์ œ๋กœ ํ•„ํ„ฐ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋จผ์ € CSSgram ์ด๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
    (์„ค์น˜๋ฐฉ๋ฒ•์€ ์•„๋ž˜ ์ฐธ๊ณ !)
  • ์ด์ œ FilterBox Component ์— ๊ฐ filter ๋“ค์ด ์ ์šฉ๋˜๋„๋ก class ์— filter ์ด๋ฆ„์„ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉํ•ด์ฃผ๋ฉด ๊ฐ ํ•„ํ„ฐ์— ํ•„ํ„ฐ๋ช…์— ํ•ด๋‹นํ•˜๋Š” ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋œ๋‹ค.

๐Ÿค CSSgram ์„ค์น˜ํ•˜๊ธฐ ๋ฐ ์‚ฌ์šฉํ•˜๊ธฐ

  • ์‚ฌ์‹ค ์ธ์Šคํƒ€๊ทธ๋žจ ํ•„ํ„ฐ๋Š” CSS ์†์„ฑ๋งŒ์œผ๋กœ๋„ ํ‰๋‚ด๋‚ด๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์™œ๋ƒํ•˜๋ฉด CSS ์†์„ฑ์„ ํ†ตํ•ด ์ฑ„๋„, ๋ช…๋„, ์„ ๋ช…๋„, ๋ธ”๋Ÿฌ์™€ ๊ฐ™์€ ํšจ๊ณผ๋ฅผ ์ค„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 
  • ์ด๋ ‡๊ฒŒ filter ์™€  linear-gradient ์†์„ฑ๋งŒ์œผ๋กœ ์ธ์Šคํƒ€๊ทธ๋žจ ํ•„ํ„ฐ๋ฅผ ์žฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์ด ๋ฐ”๋กœ CSSgram ์ด๋‹ค.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cssgram/0.1.12/cssgram.min.css" integrity="sha512-kr3JaEexN5V5Br47Lbg4B548Db46ulHRGGwvyZMVjnghW1BKmqIjgEgVHV8D7V+Cbqm/VBgo3Rcbtv+mGLoWXA==" crossorigin="anonymous" />
  • CSSgram ์„ค์น˜๋Š” ์œ„ ์ฝ”๋“œ๋ฅผ index.html ์˜ <head></head> ์— ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋๋‚œ๋‹ค.
  • ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉด ์›ํ•˜๋Š” ์ด๋ฏธ์ง€์— class="hudson" ๊ณผ ๊ฐ™์ด class ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•