HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
👻
개발 기록
/
📑
강의 정리
/
📑
class와 style 바인딩 ~ event 핸들링
📑

class와 style 바인딩 ~ event 핸들링

Created
Sep 30, 2021 09:14 PM
Type
Vue
Mento
레온
Created By

class 바인딩

<div id="app"> <button @click="toggle">toggle</button> <h1 :class="isActive? 'active' : ''" class="title">{{msg}}</h1> </div>
기본 사용법

class에 객체 데이터 연결

<div id="app"> <button @click="toggle">toggle</button> <h1 :class="{ active, 'title__small color__pink': small }" class="title">{{msg}}</h1> </div> <script> const App = { data() { return { msg: "hello vue", active: false, small: false, }; }, methods: { toggle() { this.active = !this.active; this.small = !this.small; }, }, }; const vm = Vue.createApp(App).mount("#app"); </script>
  • 객체를 이용하여 표현.
  • 객체 이름과 메소드가 같으면 생략 가능함.
  • 이름에 - 등의 부호가 들어간다면 따옴표를 써야 함. ex) :class="{ title__small': small }"
  • 이때 띄어쓰기로 두 개 이상의 클래스를 추가할 수 있음.
<div id="app"> <button @click="toggle">toggle</button> <h1 :class="classObject" class="title">{{msg}}</h1> </div> <script> const App = { data() { return { msg: "hello vue", active: false, small: false, }; }, computed: { classObject() { return { active: this.active, small: this.small, }; }, }, methods: { toggle() { this.active = !this.active; this.small = !this.small; }, }, }; const vm = Vue.createApp(App).mount("#app"); </script>
  • 작성한 객체 데이터를 데이터 부분에서 선언하는 방법임.
  • 만약 반응형 데이터를 활용해야 한다면 computed키워드로 반응형 데이터를 사용해야 함.

class에 배열 데이터 연결

<div id="app"> <h1 :class="[active, title]" class="title" @click="changTitle"> Hello Vue </h1> </div>
  • 일반 class일 경우 ['active', 'title']과 같이 사용함.
  • 위의 예시는 반응형 데이터를 이용할 경우임.

style 바인딩

inline style에 데이터 연결

  • 기존 class 데이터 연결과 동작 방식이 동일함. ex) <h1 :style="{ color, width }" @click="toBlue">Hello Vue</h1>
  • 인라인 형식의 click 이벤트 내 여러 메소드를 넣고 싶다면 @click="toBlue(); increaseWidth()"로 직접 실행해주면 됨.
  • dash case인 CSS를 camel case로 적어주어도 자동으로 변형됨. 따라서 따옴표를 사용하지 않아도 됨.
  • 두 개의 객체 데이터를 바인딩 할 때는 배열을 사용하면 됨. 이때 중복된 데이터가 있다면 나중에 선언된 객체가 우선순위를 가짐.

조건부 렌더링

<div id="app"> <h1 v-if="isShow">Hello Vue</h1> <template v-else-if="true"> <h2>Apple</h2> <h2>okay</h2> <span>doky</span> </template> <h2 v-else>Good item</h2> </div> <script> const App = { data() { return { isShow: true, }; }, }; const vm = Vue.createApp(App).mount("#app"); </script>
  • 조건부끼린 형제요소로 인접해 있어야 함.
  • template 태그를 이용해 여러 요소를 한 번에 조건으로 삼을 수 있음. template 태그는 v-if 또는 v-for 디렉티브가 있을 때 해당하는 요소를 렌더링하지 않음.

v-show

  • v-if대신 v-show를 사용할 수 있음. v-show는 display 속성에 none으로 바꿔 요소를 화면에 보여지거나 안보이게 만듦.
  • v-if는 주석처리 시키는 것임(요소 구소 자체를 사라지게 함, lazy, 초기 렌더링 비용 낮으나 전환 비용이 높음).
  • 따라서 토글을 자주할 것 같으면 v-show를 권장하나 일반적으로 v-if를 사용함.
  • 주의할 점은 이중 괄호를 이용해 데이터를 출력할 때, 데이터 전송이 느리다면 이중 괄호가 그대로 노출될 수 있음. 따라서 v-show는 v-cloak디렉티브와 함께 사용하는 것이 좋음.
  • v-cloak은 출력할 데이터가 준비되기 전까지 보여줄 스타일을 결정함(독립적으로 사용 가능). 해당 스타일에 display 값을 none으로 지정하면 컴파일 되지않은 mustache 바인딩을 숨길 수 있음.
<style> [v-cloak] { display: none; } </style> <div id="app"> <h1 v-show="isShow" v-cloak>{{ msg }}</h1> </div>
⚠️
v-if와 v-for를 함께 쓰는 걸 권장하지 않음. v-if의 우선순위가 더 높기 때문에 for문을 돌돌면서 조건을 만들면 원치 않는 결과를 반환할 수 있음. [참고]

리스트 렌더링

  • v-for로 배열 리스트를 렌더링할 수 있음. 두 번째 인자로 index 제공.
    • notion image
  • v-for를 사용하여 객체의 속성을 반복할 수 있음. 인자로 value, key, index를 제공. 단, index의 순서는 일관적이지 않음.
    • notion image
  • v-for와 :key=""속성을 같이 사용해야 함. key는 고유한 속성을 증명함.
  • push 등 배열을 직접적으로 바꾸는 변이 메소드를 사용하면 데이터 변경이 감지됨.
  • filter, slice 등 새로운 배열을 할당해야 하는 메소드 또한 기존 데이터의 값 변형을 만든다면 전부 새로 그리는 것이 아닌 바뀐 데이터만 변경함(Vue의 최적화, computed).
  • v-for의 정수를 넣으면 1부터 시작함.

컴포넌트의 v-for

  • 일반적으로 사용하는 v-bind는 한 방향으로 값을 전달하는 단방향 데이터 바인딩임.
  • 양방향으로 가능하게 하려면 v-model이란 디렉티브를 사용해야 함.
<div id="app"> <form @submit="addNewTodo"> <label for="new-todo">Add a todo</label> <input type="text" id="new-todo" placeholder="feed the cat" v-model="newTodoText" /> <button>Add</button> </form> <ul> <todo-item v-for="todo in todos" :key="todo.id" :todo="todo" @remove="removeTodo" /> </ul> </div> <script> const TodoItem = { //emit으로 커스텀 이벤트를 만들 수 있음. template: ` <li> {{ todo.title }} <button @click="$emit('remove', todo.id)">Remove</button> </li>`, //활용할 데이터를 선언 props: ["todo"], }; const App = { components: { TodoItem, }, data() { return { newTodoText: "", todos: [], }; }, methods: { addNewTodo(event) { event.preventDefault(); this.todos.push({ id: Date.now(), title: this.newTodoText, }); this.newTodoText = ""; }, removeTodo(todoId) { this.todos = this.todos.filter((todo) => { return todo.id !== todoId; }); }, }, }; const vm = Vue.createApp(App).mount("#app"); </script>
(간단한 Todo 만들기) TodoItem이란 컴포넌트 만듦.

이벤트 핸들링

  • @를 이용한 직접 바인딩. ex) <button @click="counter += 1">Add 1</button>
  • 메소드 호출을 통한 이벤트 핸들링. ex) <button @click="greet">Greet</button>
  • 매개변수를 이용한 이벤트 핸들링. ex) <button @click="say('hi')">Say hi</button>
  • 원본 DOM 이벤트에 액세스 해야할 때 $event를 사용해 메소드에 전달할 수 있음(순서 무관).
    • <div id="app"> <h1 @click="say('hi', $event)">{{msg}}</h1> </div> <script> const App = { data() { return { msg: "Vue", }; }, methods: { say(message, event) { console.log(message, event); }, }, }; const vm = Vue.createApp(App).mount("#app"); </script>
  • 하나의 이벤트에 여러 이벤트를 실행하려면 하나의 이벤트 실행 후 세미콜론 또는 쉼표로 마무리하면 됨(복합 이벤트 핸들러).

이벤트 수식어

Vue에서 제공하는 이벤트 수식어가 있음.
  • .self
  • .once
  • .passive
  • .stop
  • .prevent
  • .capture
<!-- 클릭 이벤트 전파가 중단되었습니다. --> <a @click.stop="doThis"></a> <!-- 제출 이벤트가 페이지를 다시 로드하지 않습니다. --> <form @submit.prevent="onSubmit"></form> <!-- 수정자는 체이닝이 가능합니다. --> <a @click.stop.prevent="doThat"></a> <!-- 단순히 수식어만 사용이 가능합니다. --> <form @submit.prevent></form> <!-- 캡처 모드를 사용할 때 이벤트 리스너를 사용 가능합니다.--> <!--즉, 내부 엘리먼트를 대상으로 하는 이벤트가 해당 엘리먼트에서 처리되기 전에 여기서 처리합니다. --> <div @click.capture="doThis">...</div> <!-- event.target이 엘리먼트 자체인 경우에만 트리거를 처리합니다.--> <!-- 자식 엘리먼트에서는 처리되지 않습니다.--> <div @click.self="doThat">...</div>
💡
그 외 Vue에서 수식어를 다양하게 제공하고 있음. [확인하기]