TIL. v-for 와 v-bind:class 내부 동작 본문

카테고리 없음

TIL. v-for 와 v-bind:class 내부 동작

violet4795 2021. 9. 7. 16:29

 

오늘 질문이 들어왔다.

 

v-bind:class 안에 동적으로 v-for로 각각 할당해주고 싶으시다 셨는데, 

 

제대로 동작하지 않는다고 하셨다.

 

실제 문제점만 따온 테스트용 코드인데 처음 형태는 아래와 같았다.

 

<div id="app" >
  <li v-for="(item, idx) in items" v-bind:class="{'active': 'flag' + (20 + idx)}">
    <input v-model="value[(20 + idx)]"/>
    <button @click="clk(20 + idx)" >
      {{ item.text + (20 + idx) }}
    </button>
  </li>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
  .active {
    background-color :red;
  }
</style>
<script>
  var app = new Vue({
      el: '#app',
      data: {
        items: [{text: 'flag'}, {text: 'flag'}],
        flag20: false,
        flag21: false,
        value: {20: '2020', 21: '2021'}
      },
      methods: {
        clk : function (idx) {
          console.log(this.value[idx])
          this['flag'+idx] = !this['flag'+idx]
        },
      }
    })
</script>

v-bind:class="{ active 머시기저시기 부분에서 문제가 발생하고 있는 상황이었다.

 

일단 문제점은 대략 알겠는데, 부끄럽게도 그 자리에서 확실히 설명할 수가 없었다.

 

먼저 코드상에서 확인된 이유에서는, 

 

해당 코드가 vue를 거친 후 컴파일 되면 dom 내부 prop들은 

 

vm이라는 virutal machine의 약자를 뜻하는 객체의 속성명으로 접근하게 된다.

 

즉, 아래와 같은 형태로 컴파일된다.

var render = function(){
	var vm = this;
    var _h = vm.$createElement;
    var _c = vm._self._c || _h;
    return _c.....
    ...
    
    //vm.'flag'+(20+idx)
    

  <li v-for="(item, idx) in items" v-bind:class="{'active': 'flag' + (20 + idx)}">
    <input v-model="value[(20 + idx)]"/>
    <button @click="clk(20 + idx)" >
      {{ item.text + (20 + idx) }}
    </button>
  </li>

 

 

결국 두 가지 방법을 생각해냈는데,

 

<div id="app" >
  <li v-for="(item, idx) in items" v-bind:class="{'active': calc(idx+20)}">
<!-- <li v-for="(item, idx) in items" v-bind:class="{'active': valueOf()['flag'+ (idx + 20)]}"> -->
    <input v-model="value[(20 + idx)]"/>
    <button @click="clk(20 + idx)" >
      {{ item.text + (20 + idx) }}
    </button>
  </li>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
  .active {
    background-color :red;
  }
</style>
<script>
  var app = new Vue({
      el: '#app',
      data: {
        items: [{text: 'flag'}, {text: 'flag'}],
        flag20: false,
        flag21: false,
        value: {20: '2020', 21: '2021'}
      },
      methods: {
        clk : function (idx) {
          console.log(this.value[idx])
          this['flag'+idx] = !this['flag'+idx]
        },
        calc: function(idx){
          return this['flag'+idx]
        }
      }
    })
</script>

 

첫번째는 function으로 결과를 받는것,

두번째는 vm이 객체이니까, valueOf()로 객체원형을 받아와서 

<!-- <li v-for="(item, idx) in items" v-bind:class="{'active': valueOf()['flag'+ (idx + 20)]}"> -->

객체 속성명으로 직접 접근하는 방법인데,

 

아무래도 두번째방법보다는 첫번째가 보기 쉽고, 추가 동작 구현에도 용이할 것 같아서 첫번째 방법으로 알려드렸다.

 

 

https://codepen.io/violet4795/pen/mdwOjjd