vue왜 인덱스를 고유 식별자로 사용할 수 없나요? 다음 글에서는 Vue가 인덱스를 고유 식별자로 사용할 수 없는 이유를 소개하겠습니다. 도움이 되길 바랍니다!
여기에는 네이티브 js의 DOM 작업과 가상 DOM이 가져온 최적화가 포함됩니다. 다음은 두 부분으로 나누어
먼저 DOM 노드를 기본적으로 작동하는 방법을 살펴보겠습니다. 하지만 DOM 작업에 대한 브라우저의 반응은 매우 에너지를 소모합니다. 작업(브라우저에서 페이지를 렌더링하는 과정을 참조하세요)
nbsp;html> <meta> <meta> <meta> <title>Document</title> <div> <ul></ul> </div> <script> let ul = document.querySelector('ul') for (let i = 0; i < 3; i++) { let li = document.createElement('li') li.innerHTML = i + 1 ul.appendChild(li) } </script>
또한 동적으로 변경되는 많은 js 코드로 인해 브라우저가 재정렬되고 에너지 소비가 상상해 보세요. 일부 노드가 변경되면 변경된 노드를 로컬로 재배치하면 성능이 많이 절약되지 않을까요? ? ? Vue에서 소개하는 가상 DOM은 이 방법을 사용합니다. 다음은 vue 코드의 일부입니다
nbsp;html> <meta> <meta> <meta> <script></script> <title>Document</title> <div> <ul> <item></item> </ul> <button>change</button> </div> <script> new Vue({ el: '#app', data() { return { list: [1, 2, 3] } }, methods: { change() { this.list.reverse() } }, components: { item: { props: ['num'], template: ` <div> {{num}} `, name: 'child' } } }) </script>
변경 버튼을 클릭하면
네이티브 js가 이러한 작업을 수행하면 필연적으로 발생합니다. 재배치했는데 페이지가 부분적으로 변경된 것 뿐인데 Vue는 virtual DOM을 도입한 후 에너지 소비를 크게 절감했습니다
vue에서는 렌더링 기능을 실행하기 전에 가상 노드 트리를 얻을 수 있으며, 가상 노드 트리를 사용하여 페이지를 렌더링할 수 있습니다. 페이지 DOM 노드가 동적으로 변경되면 렌더링하기 전에 새로 생성된 가상 노드가 마지막으로 생성된 가상 노드와 비교되고 다른 부분만 렌더링됩니다. 각 가상 노드는 컨테이너 레이어의 특성을 설명하는 객체입니다. 다음은 vue 코드에서 변경 버튼을 누르기 전의 가상 노드 트리입니다
vndoe = { tag: 'ul', children: [ { tag: 'li',key:0, children: [{ vnode: { text: '3' } }] }, { tag: 'li',key:1, children: [{ vnode: { text: '2' } }] }, { tag: 'li',key:2, children: [{ vnode: { text: '1' } }] } ] }复制代码
변경을 클릭하면 새로운 가상 노드 트리가 생성되어 그것과 비교됩니다
비교 후, 서로 다른 장소가 렌더링됩니다
그렇다면 두 가상 노드 수의 차이를 어떻게 찾을 수 있을까요? 여기에는 vue 소스 코드의 diff 알고리즘이 포함됩니다
라이프 사이클이 마운트된 후 데이터 소스가 변경되는 한 감시자 관찰자의 콜백이 트리거되어 뷰 업데이트를 구동합니다.
vm._update(v_rander())
_update는 차이점을 찾기 위해 _patch_에 vnode를 생성합니다
_patch_에서 시작되는 것은 diff 알고리즘입니다
key는 두 가지를 찾는 데 있어 diff 알고리즘을 더 정확하게 만들기 위한 고유 식별자입니다. 비교해야 하는 노드
이전 코드를 살펴보겠습니다. diff 알고리즘에서 키는 두 개의 가상 노드 트리가 있을 때 고유 식별자입니다. 비교하면 동일한 키 값이 발견됩니다. 비교를 통해 키 값은 동일하지만 내부 데이터가 다른 것으로 확인됩니다. diff 알고리즘은 실제로는 변경되었음을 확인하고 다시 렌더링합니다. 위치를 변경했습니다. 고유 식별자 ID를 추가하면
nbsp;html> <meta> <meta> <meta> <script></script> <title>Document</title> <div> <ul> <item></item> </ul> <button>change</button> </div> <script> new Vue({ el: '#app', data() { return { list: [{ n: 1, id: 0 }, { n: 2, id: 1 }, { n: 3, id: 2 }, ] } }, methods: { change() { this.list.reverse() } }, components: { item: { props: ['num'], template: ` <div> {{num}} `, name: 'child' } } }) </script>复制代码
diff 알고리즘이 비교를 위해 동일한 키 값을 찾은 후 해당 키가 값은 동일하지만 내부 데이터도 동일합니다. 다시 렌더링되지는 않지만 위치가 크게 변경됩니다. 브라우저 소비를 크게 절약하므로 인덱스를 키로 사용하면 diff의 최적화가 실패하게 됩니다(재사용성이 감소하고 가상 돔의 원래 의도)
nbsp;html> <meta> <meta> <meta> <script></script> <title>Document</title> <div> <ul> <li> <item></item> </li> </ul> <button>del</button> </div> <script> new Vue({ el: '#app', data() { return { list: [1, 2, 3] } }, methods: { del() { this.list.splice(0, 1) } }, components: { item: { template: '<div>{{Math.random()}}' } } }) </script>复制代码
삭제 버튼을 누른 후
실제로 마지막 항목을 삭제한 것으로 확인되었는데, 데이터를 삭제한 후 배열의 특성상 남은 데이터의 첨자 인덱스와 키가 -1로 변경되기 때문입니다. 즉, 두 번째, 3개의 데이터 키가 1, 2에서 0,1로 변경되면 diff 알고리즘은 키 0,1의 데이터 내용이 변경되고 키 3의 내용이 삭제되었다고 간주하므로 첫 번째와 두 번째 데이터를 다시 렌더링하고 삭제합니다. 세 번째 데이터인데 실제로는 세 번째 데이터를 삭제했습니다. 하나의 콘텐츠, 두 번째, 세 번째는 키 값 변경입니다. Vue는 하위 구성 요소의 텍스트 내용을 깊이 비교하지 않습니다. 키를 사용하여 비교하면 가상 DOM 트리가 잘못 작동하고 잘못 렌더링됩니다.
( 학습 영상 공유:위 내용은 Vue가 인덱스를 고유 식별자로 사용할 수 없는 이유에 대한 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!