[Vue] v-for array 변경 시 화면 렌더링 오류

SJ·2022년 6월 15일
1

문제

바꾸고자 하는 array의 값을 바꾸면 화면에서 새로 받아온 array에 맞게 화면을 표현해주는 곳에서 문제가 생겼다.

데이터는 정상적으로 불러왔고 원하는 array 객체에 할당까지 정상적으로 되는 걸 확인했지만 정작 화면은 정상적으로 렌더링되지 않는 문제가 발생 했다.

//화면 쪽
<div>
	<samplecomponent v-for="(c,i) in dashboard" :key = "i" :value="c"></samplecomponent>

</div>



//함수 쪽
<script>
	
    
    export default {
    
    	data () {
        	return {
            	dashboard : [];
            }
        },
        
        method: {
        
        	getDashboard() {
           		const vm = this;
            	vm.dashboard = [];
            //get http 로 data받아와서 필터링 후 하나씩 dashboard에 returnData푸쉬
            	vm.dashboard.push(returnData);
            
            }
        }
    }



</script>

원인 분석

샘플 코드를 보면 getDashboard함수를 실행하면 dashboard에 원하는 데이터를 하나씩 푸쉬하도록 하였다.
결과 dashboard를 보면 정상적으로 원하는 데이터로 바뀐 것을 확인 할 수 있지만 화면은 렌더링 되지 않았다.
vue는 데이터가 변경되면 화면이 바로 갱신되는 반응형 시스템을 가지고 있기 때문에 배열 변경을 감지 할 수 있는 함수를 사용하였는데 배열의 길이는 정상적으로 반영되지만 기존에 가지고 있던 데이터가 반복적으로 보이는 오류가 있었다.

--- 변경 감지 메소드

  • push(), pop(), shift(), unshift(), splice(), sort(), reverse(),

--- 변경 불가 상황

  • 인덱스로 배열에 있는 항목 직접 설정
vm.items[index] = newValue
  • 배열 길이를 수정하는 경우
vm.items.length = newLength

그러므로 다른 이유를 생각해보았는데 처음 dashboard가 1,2,3,4,5 를 가지고 있다고 가정하면 함수를 통해 나온 결과 dashboard가 4만 가진다면 화면에는 1이 표기되는 상황이라는 것을 알게 되었고 key 값 할당에 오류가 있다고 생각하였다.

v-for의 key는 고유한 ID가 되어야하는데 key를 지정해주면 가상DOM은 key를 추척하여 매칭되는 노드를 업데이트하므로 리렌더링 되는 과정에서 중복이 없게 하여야했다.

  • 참고 - key는 실제로 렌더링 되지 않기 때문에 형제 노드끼리만 고유한 값이면 된다.

해결

array 할당 문제인지 확인해보려고 computed를 사용한 뒤에 문제 없음 인지 하고 v-for 의 :key부분을 고유값으로 수정하였다.

//화면 쪽
<div>
	<samplecomponent v-for="c in getdashboard" :key = "c.pk" :value="c"></samplecomponent>

</div>



//함수 쪽
<script>
	
    
    export default {
    
    	data () {
        	return {
            	dashboard : [];
            }
        },
        computed : {
      		getdashboard: function () {
        		const vm = this
               //console.log(this.dashboard)
	        return vm.dashboard;
          	},
        },
        
        method: {
        
        	getDashboard() {
           		const vm = this;
            	vm.dashboard = [];
            //get http 로 data받아와서 필터링 후 하나씩 dashboard에 returnData푸쉬
            	vm.dashboard.push(returnData);
            
            }
        }
    }



</script>

profile
효율적이고 효과적이게

0개의 댓글