원쌤의 Vue.js 퀵스타트 책을 보았다(Vue3)_5

2023. 12. 29. 10:19뷰(Vue)

반응형

이 글은 주 단위로 하던 스터디를 개인적으로 정리하는 글입니다.

이전글에서 5장까지 작성했는데 6장에는 그냥 CSS를 어떤방식으로 사용 할 수 있는지에 대한 설명이 대부분 이였다.

 

특정 변수값을 v-bind중 하나인 style에 넣어서 적용 시킬수도 있고 class에 추가 할 수도 있고 다양한 형태를 지원한다. 

 

스타일(css) 적용에 대한 내용이다.

css의 적용은 기본적으로 동일하다.

요소의 기본 스타일 —> class로 명명된 순서에 따른 스타일적용 —> 인라인 스타일 적용.

ex) .test와 .over라는 클래스를 각각 명시했고 동일한 부분이 존재한다면 마지막에 명시한 스타일을 따라간다.

기본적으로 Vue에서도 인라인 스타일을 권장하지는 않는다.

그래도 사용해야하는 경우가 있다면 data 영역에 미리 명시를 해 두고 v-bind:style로 연결하여 사용한다.(06)

<div id="app">
      <button id="a" :style="style1" @mouseover.stop="overEvent" @mouseout.stop="outEvent">테스트</button>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script type="text/javascript">
      var vm = Vue.createApp({
        name: "App",
        data() {
          return {
            style1: { backgroundColor: "aqua", color: "black" },
          };
        },
        methods: {
          overEvent() {
            this.style1.backgroundColor = "purple";
            this.style1.color = "yellow";
          },
          outEvent() {
            this.style1.backgroundColor = "aqua";
            this.style1.color = "black";
          },
        },
      }).mount("#app");
    </script>

또한 각각의 요소를 하나씩 변경하는게 아닌 여러개를 명시하여 적용이 가능하다.(06-04)

<div id="app">
      <button id="btn1" :style="[ myColor, myLayout ]">버튼1</button>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script type="text/javascript">
      var vm = Vue.createApp({
        name: "App",
        data() {
          return {
            myColor: { backgroundColor: "purple", color: "yellow" },
            myLayout: { width: "150px", height: "80px", textAlign: "center" },
          };
        },
      }).mount("#app");
    </script>

스타일은 다음과 같고 클래스를 적용하는건 비슷하게 동작한다. v-bind:class로 연결하여 사용하는 형태.

<style>
      .buttonColor {
        background-color: aqua;
        color: black;
      }
      .buttonLayout {
        text-align: center;
        width: 120px;
      }
      .staticBorder {
        border: khaki dashed 1px;
      }
    </style>

<div id="app">
      <button class="staticBorder" :class="myColor">테스트 버튼</button>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script type="text/javascript">
      var vm = Vue.createApp({
        name: "App",
        data() {
          return {
            myColor: "buttonColor buttonLayout",
          };
        },
      }).mount("#app");
    </script>

하나씩 적용하는게 가능하여 myColor로 묶어서 여러개를 적용 시키는 모습을 볼 수 있다.

data에 지정된 true, false값을 연동하여 동적으로 class를 변경하는 형태의 코드도 제공한다. (06-07)

    <head>
    <meta charset="utf-8" />
    <title>06-07</title>
    <style>
      .buttonColor {
        background-color: aqua;
        color: black;
      }
      .buttonLayout {
        text-align: center;
        width: 120px;
      }
      .staticBorder {
        border: khaki dashed 1px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <input type="checkbox" v-model="isMyLayout" />레이아웃 적용 여부<br />
      <button class="staticBorder" :class="[myColor, isMyLayout ? myLayout : '' ]">테스트 버튼</button>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script type="text/javascript">
      var vm = Vue.createApp({
        name: "App",
        data() {
          return {
            myColor: "buttonColor",
            myLayout: "buttonLayout",
            isMyLayout: false,
          };
        },
      }).mount("#app");
    </script>
  </body>
 

아니면 아예 객체로 연결하여 편리하게 사용하는 형태로도 가능하다.

<head>
    <meta charset="utf-8" />
    <title>06-06</title>
    <style>
      .bColor {
        background-color: aqua;
        color: black;
      }
      .bLayout {
        text-align: center;
        width: 120px;
      }
      .bBorder {
        border: khaki dashed 1px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <button :class="myStyle">버튼1</button>
      <p>
        <input type="checkbox" v-model="myStyle.bColor" value="true" />색상<br />
        <input type="checkbox" v-model="myStyle.bLayout" value="true" />정렬,크기<br />
        <input type="checkbox" v-model="myStyle.bBorder" value="true" />테두리선<br />
      </p>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script type="text/javascript">
      var vm = Vue.createApp({
        name: "App",
        data() {
          return {
            myStyle: { bColor: false, bLayout: false, bBorder: false },
          };
        },
      }).mount("#app");
    </script>
  </body>
 

계산된 속성(computed) 에서 특정 값의 변화에 따라 화면에 css 등의 변화를 줄 수도 있다.(06-10)

<head>
    <meta charset="utf-8" />
    <title>06-10</title>
    <style>
      .score {
        border: solid 1px black;
      }
      .warning {
        background-color: skyblue;
        color: purple;
      }
      .warnimage {
        width: 18px;
        height: 18px;
        top: 5px;
        position: relative;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div>
        <p>1부터 100까지만 입력가능합니다.</p>
        <div>
          점수 : <input type="text" class="score" v-model.number="score" :class="info" />
          <img src="https://contactsvc.bmaster.kro.kr/img/error.png" class="warnimage" v-if="info.warning" title="1부터 100까지만 입력하세요." />
        </div>
      </div>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script type="text/javascript">
      var vm = Vue.createApp({
        name: "App",
        data() {
          return { score: 50 };
        },
        computed: {
          info() {
            return { warning: this.score < 1 || this.score > 100 };
          },
        },
      }).mount("#app");
    </script>
  </body>

data영역에 선언된 데이터들을 건드려서 DB나 비동기 없이 TODO list를 컨트롤 하는 부분이 책에 실려있다.(06-14)

    
    <!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>06-14</title>
    <link rel="stylesheet" href="https://unpkg.com/bootstrap@5.2.3/dist/css/bootstrap.min.css" />
    <style>
      body {
        margin: 0;
        padding: 0;
        font-family: sans-serif;
      }
      .title {
        text-align: center;
        font-weight: bold;
        font-size: 20pt;
      }
      .todo-done {
        text-decoration: line-through;
      }
      .container {
        padding: 10px 10px 10px 10px;
      }
      .panel-borderless {
        border: 0;
        box-shadow: none;
      }
      .pointer {
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    <div id="app" class="container">
      <div class="card card-body bg-light">
        <div classe="title">:: Todolist App</div>
      </div>
      <div class="card card-default card-borderless">
        <div class="card-body">
          <div class="row mb-3">
            <div class="col">
              <div class="input-group">
                <input
                  id="msg"
                  type="text"
                  class="form-control"
                  name="msg"
                  placeholder="할일을 여기에 입력!"
                  v-model.trim="todo"
                  @keyup.enter="addTodo"
                />
                <span class="btn btn-primary input-group-addon" @click="addTodo">추가</span>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col">
              <ul class="list-group">
                <li
                  v-for="todoitem in todolist"
                  :key="todoitem.id"
                  class="list-group-item"
                  :class="{ 'list-group-item-success': todoitem.completed } "
                  @click="toggleCompleted(todoitem.id)"
                >
                  <span class="pointer" :class="{ 'todo-done': todoitem.completed }">
                    {{todoitem.todo}} {{ todoitem.completed ? "(완료)" : "" }}
                  </span>
                  <span class="float-end badge bg-secondary pointer" @click.stop="deleteTodo(todoitem.id)"
                    >삭제</span
                  >
                </li>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script type="text/javascript">
      var ts = new Date().getTime();
      var vm = Vue.createApp({
        name: "App",
        data() {
          return {
            todo: "",
            todolist: [
              { id: ts, todo: "자전거 타기", completed: false },
              { id: ts + 1, todo: "딸과 공원 산책", completed: true },
              { id: ts + 2, todo: "일요일 애견 카페", completed: false },
              { id: ts + 3, todo: "Vue 원고 집필", completed: false },
            ],
          };
        },
        methods: {
          addTodo() {
            if (this.todo.length >= 2) {
              this.todolist.push({ id: new Date().getTime(), todo: this.todo, completed: false });
              this.todo = "";
            }
          },
          deleteTodo(id) {
            let index = this.todolist.findIndex((item) => id === item.id);
            this.todolist.splice(index, 1);
          },
          toggleCompleted(id) {
            let index = this.todolist.findIndex((item) => id === item.id);
            this.todolist[index].completed = !this.todolist[index].completed;
          },
        },
      }).mount("#app");
    </script>
  </body>
</html>
 
 

그리고 나중에 기억에 남는 부분은 특정 컴포넌트에만 적용될 수 있도록 스코프를 지정 할 수 있는게 있었다.(8장에서 소개해주더라)

 

 

 

 

반응형