관리 메뉴

여름 언덕에서 배운 것

HTML 복잡해보이면 컴포넌트 Component 만들어 쓰셈 본문

가랑비에 옷 젖는 줄 모른다 💻/Vue.js

HTML 복잡해보이면 컴포넌트 Component 만들어 쓰셈

잔뜩 2023. 9. 27. 02:02

https://codingapple.com/

 

코딩애플 온라인 강좌 - 개발자도 단기완성!

단연 NO1 강사님의 NO.1 강의 역시나 명강입니다. IT 업계의 대치동 NO1. 강사같은 엄청난 강의력. 코딩애플님의 강의는, 엄청나게 기초적인 것부터 가르치는 듯 보이지만, 실제로 다루는 깊이는 절

codingapple.com

(업데이트사항) 이제 컴포넌트.vue 이름은 귀찮게 2단어 이상으로 작명해야합니다 안그러면 에러로 잡아줌 

DiscountBanner.vue 이런 식으로 2단어로 작명 잘하면 됩니다.  

싫으면 package.json 파일 열어서 "rules" 라는 항목에

"rules": {
   "vue/multi-word-component-names": "off"
} 

한줄 추가하고 미리보기 껐다가 다시 띄우면 됩니다

 

 

 

모달창안에 꾸며오라는 저번시간 숙제는 어떻게 했냐면

 

대충 실제 상품들 다 박아오라고 했습니다.

그래서 이미지, 가격, 내용 이런 것들을 추가했다고 합니다. 

 

<div class="black-bg" v-if="모달창열렸니 == true">
  <div class="white-bg">
    <img :src="원룸들[누른거].image" style="width:100%">
    <h4>{{ 원룸들[누른거].title }}</h4>
    <p>{{ 원룸들[누른거].content }}</p>
    <p>{{ 원룸들[누른거].price }} 원</p>
    <button @click="모달창열렸니 = false">닫기</button>
  </div>
</div>

 

 

HTML 짜다보면 <div> 수십개 나오는게 일상입니다.

이게 싫으면 컴포넌트를 만들어서 사용하면 됩니다. 

원하는 HTML 덩어리를 한 글자로 축약할 수 있게 도와주는 문법이 컴포넌트입니다.

 

 

 

 

할인배너를 하나 만들고 싶습니다

 

지금 원룸 결제하면 20% 할인해준다고 배너를 띄우고 싶어진 겁니다. 

그래서 하나 HTML로 만들어봤습니다.

 

<div class="discount">
  <h4>지금 결제하면 20% 할인</h4>
</div>

근데 이 코드가 너무 길고 복잡한겁니다. 

안그래보이지만 그렇다고 가정해봅시다. 

그럴 때 긴 HTML을 짧게 축약하는 컴포넌트문법을 쓰시면 됩니다. 

 

 

 

 

 

컴포넌트 만드는 법

 

컴포넌트 만드는 법을 요약하자면 

어쩌구.vue 파일을 아무데나 만드신 후 그 안에 축약할 HTML을 붙여넣어줍니다. 

.vue 파일은 항상 이런 형식으로 만드셔야합니다. 

(예를 들면 Discount.vue)

<template>
  축약할 HTML~~
</template>

<script>
export default {
  name : '작명',

}
</script>
<style>
  넣을 스타일 
</style>

이 vue파일을 하나의 컴포넌트라고 부릅니다. 

그 다음에 원하는 곳에서 어쩌구.vue 파일을 1. import하고 2. 등록하고 3. 쓰면 됩니다. 

그럼 길고 더러운 HTML을 깔끔하게 한 글자로 축약해서 적어넣을 수 있습니다.

참고로 name : 어쩌구로 작명도 가능합니다. 나중에 디버깅할 때 쓰는 이름입니다. 

 

 

 

 

컴포넌트 쓰는 법

 

원하는 곳에서 어쩌구.vue 파일을 1. import하고 2. 등록하고 3. 쓰면 됩니다. 

 

import Discount from './Discount.vue 경로'

export default {
  data() {

  },
  components : {
    Discount,
  }
}

1. 아까 만들어둔 vue 파일을 import하고

2. 등록하는건 위와 같이 <script>안에 작성해주면 됩니다.

components 라는 항목이 이미 있으면 그거 쓰시고 없으면 하나 만드십시오. 

 

3. 그럼 이제 <template> 안에서 자유롭게 가져다쓸 수 있습니다.

<Discount>
<Discount/>

이런 식으로 원하는 곳 아무데나 사용가능합니다.

 

 

 

Q. 복잡해보이는데 굳이 왜씀?

 

- 그냥 <div>여러개 있는거 보기싫으면 씁니다 

- 다른 곳에서도 같은 HTML 재사용이 쉬워집니다. Vue 파일을 import하고 등록하고 쓰면 되니까요.

- 나중에 라우터로 페이지 구분하고 싶으면 하나의 페이지는 하나의 컴포넌트로 만드는게 좋습니다 

 

 

 

 

모달창도 컴포넌트화 해봅시다

 

드디어 컴포넌트로 축약해볼 요소를 하나 찾은 것 같습니다. 

전에 만들어놨던 모달창 코드는 매우 길고 복잡합니다.

이걸 쉽게 축약해봅시다. 

Modal.vue를 만들고 직접 긴 HTML을 짧게 축약해보십시오. 

 

 

다만 이렇게 쓰는 경우 문제가 있는데

- 모달창이 안열리는데요?

데이터바인딩할 때 문제가 생겨서 그렇습니다. 

해결은 다음 강의에서 해봅시다. 

 

그래서 대충 막 컴포넌트 100만개 만드시면 안됩니다.

코드가 복잡해질 수 있으니 각오하고 만드시면 됩니다. 

 

Modal.vue

<template>
  <div class="black-bg" v-if="모달창열렸니==true">
    <div class="white-bg">
      <img :src="원룸들[누른거].image" style="width:50%;" alt="">
      <h4>{{원룸들[누른거].title}}</h4>
      <p>{{원룸들[누른거].price }}</p>
      <p>{{원룸들[누른거].content }}</p>
      <button @click="모달창열렸니=false">닫기</button>
    </div>
  </div>
  
</template>

<script>

export default {
    name: 'Modal',
   
}
</script>

<style>
.black-bg{
  width: 100%; height: 100%;
  background: rgba(0,0,0,0.5);
  position: fixed; padding : 20px;
}
.white-bg{
  width: 100%; background: white;
  border-radius: 8px;
  padding: 20px;
}
</style>

App.vue

모달 컴포넌트화 해서 import 했는데 작동이 안되네 왜그러지?

데이터바인딩 문제 때문에 그런다. 컴포넌트 만들면 데이터바인딩 할 때 귀찮아 질 수있다.

<template>
  <Modal/>
  <DiscountBanner/>
  <div class="menu">
    <a v-for="작명 in 메뉴들" :key="작명">{{ 작명 }}</a>
  </div>

  <div v-for="(room,i) in 원룸들" :key="i">
    <img :src="room.image" class="room-img" alt="">
    <h4 @click="모달창열렸니=true; 누른거 = i">{{room.title}}원룸</h4>
    <p>{{room.price}}</p>
  </div>

</template>

<script>
import data from './assets/oneroom';
import DiscountBanner from './components/DiscountBanner.vue';
import Modal from './components/Modal.vue';

export default {
  name: 'App',
  data() { 
    return {
      누른거 : 0,
      원룸들 : data,
      //products: ['신촌', '낙성대', '송파'],
      신고수 : [0,0,0],
      메뉴들 : ['Home','Shop','About'],
      모달창열렸니 : false
    }
  },  
  methods: {
    increase(index) { 
      this.신고수[index] += 1;
    }
  },
  components: {
    // DiscountBanner : DiscountBanner, 같으면 한번만 써도된다.
    DiscountBanner,Modal

  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
body{
  margin : 0
}
div{
  box-sizing: border-box;
}
.room-img{
  width : 100%;
  margin-top: 40px;
}
.menu{
  background:  darkslateblue;
  padding: 15px;
  border-radius: 5px;
}
.menu a {
  color: white;
  padding: 10px;
}

</style>

 

728x90