vue, 가변 배열에 v-for을 사용하여 key 값을 index로 사용시 문제점

ecof·2022년 4월 4일
0

토이프로젝트 도중 v-for을 사용하여 만든 리스트의 삭제 함수를 만들었더니 버그가 발생했다.
포지션이 absolute에 임의의 위치를 가진 listitem1 과 마찬가지인 listitem2 가 존재할때 1녀석을 삭제했더니 2가 1의 위치에 가버리는 버그였다.

두시간정도 검색을 해보고 각종 함수들을 뜯어보다가 문제점을 찾지 못하던 도중 개발자 도구로 유심히 element가 변하는 모습을 지켜보니 listitem1을 삭제할때 listitem1에 해당하는 element가 삭제되고 그 위로 listitem2가 올라가는게 아닌, listitem2가 삭제가 되고 listitem1의 id 나 내용이 다른 함수에서 넣어준 임의의 위치값을 제외하고 listitem2의 정보로 바뀌고 있었다.

????????

이게 뭘까 하던 도중 설마하고 바꿔본 key 값이 정답이었다. 어디선가, 선생님인가 유튜브인가 key값을 꼭 사용해줘야 하고 또 단순한 index가 아닌 유니크한 값을 사용하라고 들었었는데 이유는 듣지 못했었건만, 그 문제점을 직접 겪을줄은 몰랐다.

  <div id="app">
    <!-- index를 key로 사용한 v-for -->
    <h1 style="position: absolute;">index key</h1>
    <div
    v-for="(n, i) in list1" :key="i"
    :style="{backgroundColor : n.color}" style="position: absolute; width: 200px; height: 190px;"
    class="div1">
      {{n.name}} <button @click="remove(n.id)">삭제</button>
    </div>

    <!-- 문자열 + id값을 key로 사용한 v-for -->
    <h1 style="position: absolute; left: 220px;">no index key</h1>
    <div
    v-for="(n, i) in list2" :key="n.id"
    :style="{backgroundColor : n.color}" style="position: absolute; width: 200px; height: 190px; left:220px;"
    class="div2">
      {{n.name}} <button @click="remove2(n.id)">삭제</button>
    </div>
  </div>

v-for을 이용하여 만든 두개의 리스트


만들어진 화면

	new Vue({
      el : "#app",
      data: {
        list1 : [
          {name : "첫번째 박스", id : 0, color: "red"},
          {name : "두번째 박스", id : 1, color: "blue"},
          {name : "세번째 박스", id : 2, color: "green"},
          {name : "네번째 박스", id : 3, color: "orange"}
        ],
        list2 : [
          {name : "첫번째 박스", id : 0, color: "red"},
          {name : "두번째 박스", id : 1, color: "blue"},
          {name : "세번째 박스", id : 2, color: "green"},
          {name : "네번째 박스", id : 3, color: "orange"}
        ],
      },
      methods: {
        // 삭제 메소드
        remove(id) {
          this.list1.forEach((element , i)=> {
            if (element.id == id) {
              this.list1.splice(i, 1)
            }
          });
        },
        remove2(id) {
          this.list2.forEach((element , i)=> {
            if (element.id == id) {
              this.list2.splice(i, 1)
            }
          });
        }
      },
    })

    // 외부에서 정해주는 위치값
    let div = document.getElementsByClassName('div1')
    for (let i = 0; i < div.length; i++) {
      div[i].style.top = 100 + (190 * (i)) + 'px'
    }

    let div2 = document.getElementsByClassName('div2')
    for (let i = 0; i < div2.length; i++) {
      div2[i].style.top = 100 + (190 * (i)) + 'px'
    }

vue 코드와 위치값을 정해주는 자바스크립트

여기서 각각 두번째 박스를 삭제하게 되면 이런 모양새가 된다.

profile
프론트엔드 개발 지망

0개의 댓글