7강: class & style Binding

yuriring·2023년 4월 7일
0

VueMastery

목록 보기
6/6
post-thumbnail

강의 목표 : 아래와 같은 화면을 class와 스타일 바인딩으로 좀 더 예쁘게 꾸며보자

쇼핑몰을 이렇게 꾸며놓고 오픈하면 바로 망한다..

how can we show the variant colors themsleves using style binding?


1. variant div에 .color-circle class를 추가한다.

//index.html
<div v-for="variant in variants" 
:key="variant.id" 
@mouseover="updateImage(variant.image)"
class="color-circle">
  {{ variant.color }}
</div>

//style.css
.color-circle {
  width: 50px;
  height: 50px;
  margin-top: 8px;
  border: 2px solid #d8d8d8;
  border-radius: 50%;
}

2. color-circle 클래스 옆에 v-bind로 스타일바인딩한다.

//index.html
<div v-for="variant in variants" 
:key="variant.id" 
@mouseover="updateImage(variant.image)"
class="color-circle"
//style binding 하기
:style = "{ backgroundColor: variant.color }"
>
</div>

결과

짜잔~ 글자 대신 색상 원이 나타남


How is this working under the hood?

  • 반복으로 돌면서 차례대로 배경색을 뱉어냄

반복문을 돌듯이 배경색을 뱉어낸다.

style Biding 사용시 주의점

Camel vs. Kebab

  • camel case : 두단어 사이를 붙이고 두번째 단어에 대문자 삽입 (마치 낙타 혹 같아서)
<div :style={ backgroundColor : variant.color}></div>
  • kebab case : 단어 사이 '-' 삽입 ( 꼬챙로 고기 꽂은 케밥 같아서)
//틀린 예. 아래에서 자세히 설명
<div :style={ background-color : variant.color}></div>

  • style object는 Javascript이기 때문에 속성 이름에 camel case를 사용했다. 만약 backgroundColor를 camel case가 아닌 kebab case로 사용한다면 자바스크립트가 마이너스 기호로 해석했을 것이다.


    그래도! 무슨일이 있어도! 나는 kebab case를 사용해야겠다!!
    : kebab case를 반드시 'quote' 사이에 넣어주자
<div :style={ 'background-color' : variant.color}></div>

Style Binding: Objects

만약에 여러개의 스타일을 사용하고 싶은데 한 줄로 주르륵 늘여놓으면 코드를 읽기 어려워진다. 이것을 어떻게 표현해야 할까?
: main.js의 데이터에 객체로 넣기

예제

//main.js
data(){
  return{
    styles:{
      color: 'red',
      fontSize:'14px'
      margin-left: '50px';
      padding: '20px';
    }
  }
}

//index.html
<div style="color: red; font-size: 14px; margin-left: 50px; padding: 20px"></div> 

data의 스타일 객체 이름만 삽입해서 모든 스타일 객체 내용을 한번에 바인딩한다.

//index.html
<div style="styles"></div> 

Class Binding

instock data value가 false면 out of stock으로 바뀌는데 현 코드에는 아직도 카트의 숫자가 올라간다. 카드 숫자가 올라가지 않게 instock이 false면 add to cart 가 disable 되게 만들자.


1. 굉장히 간단함. 버튼에 :disabled="!inStock" 추가

//index.html
<button
	class="button"
	:disabled="!inStock"
	@click="addToCart"> 
      Add to Cart
</button>

재고가 없으면 'Add to Cart'를 눌러도 장바구니의 갯수가 늘어나지 않는다. 하지만 아직도 'Add to Cart' 버튼을 눌러도 될 것 같아 보인다! 그러면 어떻게?


2. 클래스 바인딩을 이용하여 disabled 버튼 클래스를 추가한다.

//styles.css 
.disabledButton {
  background-color: #d8d8d8;
  cursor: not-allowed;
}

//index.html
<button
	class="button"
	:class="{disabledButton: !inStock}"
	:disabled="!inStock"
	@click="addToCart"> 
      Add to Cart
</button>

결과

누가봐도 재고 없어서 클릭버튼이 동작하지 않을 것 같이 생겼다.
실제로 마우스 커서를 addto cart에 올리면 금지 아이콘이🚫 뜬다

뷰 개발창, 혹은 console에서 mountedApp.inStock = true로 변경하면 버튼이 다시 원래 색으로 돌아오면서 수량 추가를 할 수 있다.

Class Binding 다른 예제 :

1. Mutiple classes

클래스가 여러개 있는데 하나로 합치고 싶으면?

그냥 하나로 합쳐라.


<div class="color-circle"
	:class="{active : activeClass}"></div>
    
//⬆️이 코드를 ⬇️이렇게

<div class="color-circle active"></div>

2. Ternary operators (보조연산자)

  • 3항 연산자를 사용하여 조건에 따라 다른 클래스를 추가할 수 있는 기능

    activeClass가 true

//activeClass 이름만 남기고 모두 생략 가능

<div class="activeClass"></div>


code challenge
1. Bind the out-of-stock-img class to the image whenever inStock is false


code challenge answer

//index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue Mastery</title>
    <!-- Import Styles -->
    <link rel="stylesheet" href="./assets/styles.css" />
    <!-- Import Vue.js -->
    <script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>
  </head>
  <body>
    <div id="app">
      <div class="nav-bar"></div>

      <div class="cart">Cart({{ cart }})</div>
      
      <div class="product-display">
        <div class="product-container">
          <div class="product-image">
            <!-- solution -->
            <img :class="{ 'out-of-stock-img': !inStock }" v-bind:src="image">
            <!-- solution -->
          </div>
          <div class="product-info">
            <h1>{{ product }}</h1>
            <p v-if="inStock">In Stock</p>
            <p v-else>Out of Stock</p>
            <ul>
              <li v-for="detail in details">{{ detail }}</li>
            </ul>

            <div 
              v-for="variant in variants" 
              :key="variant.id" 
              @mouseover="updateImage(variant.image)" 
              class="color-circle" 
              :style="{ backgroundColor: variant.color }">
            </div>
            
            <button 
              class="button" 
              :class="{ disabledButton: !inStock }" 
              :disabled="!inStock" 
              @click="addToCart">
              Add to Cart
            </button>
          </div>
        </div>
      </div>
    </div>

    <!-- Import App -->
    <script src="./main.js"></script>

    <!-- Mount App -->
    <script>
      const mountedApp = app.mount('#app')
    </script>
  </body>
</html>

//main.js

const app = Vue.createApp({
    data() {
        return {
            cart:0,
            product: 'Socks',
            brand: 'Vue Mastery',
            image: './assets/images/socks_blue.jpg',
            inStock: false,
            details: ['50% cotton', '30% wool', '20% polyester'],
            variants: [
              { id: 2234, color: 'green', image: './assets/images/socks_green.jpg' },
              { id: 2235, color: 'blue', image: './assets/images/socks_blue.jpg' },
            ]
        }
    },
    methods: {
        addToCart() {
            this.cart += 1
        },
        updateImage(variantImage) {
            this.image = variantImage
        }
    }
})
profile
FE 개발자가 되기 위해 달리고 있어요 🏃‍♀️

0개의 댓글