frontend/Vue.js

[vue3/composition API] :class로 event.target 대체하기

김포레스트 2023. 8. 3. 14:38

버튼을 클릭 했을 때, 배경색상이 바뀌도록 하고 싶다.

아마 버튼을 클릭 했을 때, class를 추가해달라고 부탁할 것이고,

class가 추가되면 css 가 변경되는 방식으로 코딩 했을 것이다. 

 

기존의 방식은 '클릭한 걔'에 초점을 맞추어 이벤트를 감지하도록 하는 것이었다.

예시 코드는 이렇다.

 

**템플릿**

    <div class="static">
      <span @click="test(1, $event)"> 초록으로</span>
      <span @click="cancel(1, $event)"> 핑크로 </span>
    </div>
    <div class="static">
      <span @click="test(2, $event)"> 초록으로</span>
      <span @click="cancel(2, $event)"> 핑크로 </span>
    </div>
    <div class="static">
      <span @click="test(3, $event)"> 초록으로</span>
      <span @click="cancel(3, $event)"> 핑크로 </span>
    </div>

 

 

** js(script setup) **

const test = (index, event) => {
  event.target.closest('.static').classList.add('active');
}

const cancel = (index, event) => {
  event.target.closest('.static').classList.remove('active');
}

 

** css (style lang="scss") **

.static {
  display: inline-block;
  margin: 10px 20px;
  padding: 20px;
  background: pink;

  &.active {
    background: rgb(168, 240, 174);
  }
  
  > span {border: 1px solid gray; padding: 5px; border-radius: 5px;}
  > span + span {margin-left: 10px}
}

 

이러면 초록으로 버튼을 누르면 부모요소인 div.static에 클래스 active가 추가로 붙으면서 색상이 변경된다.

컴포넌트가 몇개가 들어가건 관계 없이 event.target을 쓰면 '클릭한 걔!!!!!'의 무엇무엇을 바꾸어 줄 수 있다.

그래서 주로 element의 css를 변경하고 싶을 때 사용하곤 했다. 

 

그러나 하나의 컴포넌트에서 evnet가 다수 발생 할 때에는 사용하기 어렵다는 단점이 있기 때문에, 다른 방법을 찾아보았다. 클릭한 걔 에 초점을 맞추기 보다, class를 추가, 삭제 한다는 것에 초점을 두니 클래스를 바인딩하는  방법을 활용 하게 되었다. 역시 공식 문서가 답을 주었다.

 

https://ko.vuejs.org/guide/essentials/class-and-style.html#binding-html-classes

 

클래스와 스타일 바인딩 | Vue.js

 

ko.vuejs.org

 

class를 반응형 객체로 만들어서 반환해주는 것이다. 

너무 어려우니 일단 예제를 보자. (css코드는 동일하다)

 

 

**템플릿**

    <div class="static" :class="testObj.obj1">
      <span @click="test(1)">dd/ {{ testObj.obj1.active }} </span>
      <span @click="cancel(1)">cancel / {{ testObj.obj1.active }}</span>
    </div>
    <div class="static" :class="testObj.obj2">
      <span @click="test(2)">dd/ {{ testObj.obj2.active }} </span>
      <span @click="cancel(2)">cancel / {{ testObj.obj2.active }}</span>
    </div>
    <div class="static" :class="testObj.obj3">
      <span @click="test(3)">dd/ {{ testObj.obj3.active }} </span>
      <span :class="testObj.obj3" @click="cancel(3)">cancel / {{ testObj.obj3.active }}</span>
    </div>

 

 

** js(script setup) **

const testObj = {
  obj1 : reactive({
    active: true,
  }),
  obj2 : reactive({
    active: true,
  }),
  obj3 : reactive({
    active: true,
  }),
}

const test =index=> {
  testObj['obj'+index].active = false;
}

const cancel =index=> {
  testObj['obj'+index].active = true;
}

 

 

** 출력된 모습 **

클래스를 반응형 객체로 만들어 놓은 다음에

컴포넌트에는 객체의 key 값만 바인딩 해주면 됨.

 

그리고 클릭했을 때, value 값을 true/false로 바꿔 주면 되는 것이다. 

이 예제에서는 dd 버튼을 누르면 true였던 초기값이 false로 바뀌면서 class active가 remove 된다.

그리고 cancel 버튼을 누르면 false였던 값이 true로 바뀌면서 class active가 add 된다.

 

 

여기서 퀴즈~! 그럼 버튼 하나를 사용 해서 토글 기능을 만들 수도 있을까!? 

있다.

 

정답은 하단에!! 

    <div class="static" :class="testObj.obj4" @click="toggleTest(4)">클릭하면 색깔이 바뀜</div>

 

const testObj = {
  obj1 : reactive({
    active: true,
  }),
  obj2 : reactive({
    active: true,
  }),
  obj3 : reactive({
    active: true,
  }),
  obj4 : reactive({
    active: false,
  }),
}


const toggleTest =index=> {
  if (testObj['obj'+index].active === true) { 
    testObj['obj'+index].active = false;
  } else {
    testObj['obj'+index].active = true;
  }
}

 

이렇게 하면 된다. 

끗!