멍
TIL. v-for 와 v-bind:class 내부 동작 본문
오늘 질문이 들어왔다.
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)]}"> -->
객체 속성명으로 직접 접근하는 방법인데,
아무래도 두번째방법보다는 첫번째가 보기 쉽고, 추가 동작 구현에도 용이할 것 같아서 첫번째 방법으로 알려드렸다.