Vue 가상 Dom 과 diff 알고리즘 을 알 아 보 는 글
Vue 와 React 를 사용 한 파트너 는 가상 Dom 과 diff 알고리즘 에 익숙 하고 중요 한 역할 을 할 것 입 니 다.소 편 은 Vue 와 접촉 하 는 것 이 비교적 많 기 때문에 React 는 얕 은 학문 일 뿐 이 므 로 본 편 은 주로 Vue 에 대해 소 개 를 하고 한 걸음 한 걸음 알 아 보 겠 습 니 다.
가상 DOM
가상 DOM 이란 무엇 입 니까?
가상 DOM(가상 DOM) Dom),즉 우리 가 흔히 말 하 는 가상 노드 는 JS 대상 으로 실제 DOM 중의 노드 를 모 의 하 는 것 이다.이 대상 은 실제 DOM 의 구조 와 속성 을 포함 하고 가상 DOM 과 실제 DOM 의 차 이 를 비교 하여 부분 적 인 렌 더 링 을 하여 성능 을 최적화 하 는 목적 을 달성 하 는 데 사용 된다.
실제 요소 노드:
<div id="wrap">
<p class="title">Hello world!</p>
</div>
VNode:
{
tag:'div',
attrs:{
id:'wrap'
},
children:[
{
tag:'p',
text:'Hello world!',
attrs:{
class:'title',
}
}
]
}
가상 DOM 을 왜 사용 합 니까?가상 DOM 에 대해 간단히 알 고 나 면 Vue 와 React 프레임 워 크 에 왜 사용 되 느 냐 고 물 어 보 는 파트너 가 있 지 않 습 니까?좋 은 문제!그럼 동료 들 의 의문 을 해결 해 보 자.
처음에 우 리 는 JS/JQuery 를 사용 할 때 DOM 을 대량으로 조작 할 수 밖 에 없 었 고 DOM 의 변 화 는 환류 나 재 그림 을 일 으 켜 페이지 렌 더 링 성능 을 떨 어 뜨 렸 다.그러면 어떻게 하면 DOM 에 대한 조작 을 줄 일 수 있 을까요?이때 가상 DOM 응용 프로그램 이 생 겨 났 기 때문에 가상 DOM 이 나타 난 주요 목적 은 잦 은 DOM 조작 을 줄 이기 위해 환류 재 그림 으로 인 한 성능 문 제 를 일 으 키 는 것 입 니 다!
가상 DOM 의 역할 은 무엇 입 니까?
그렇다면 가상 DOM 과 실제 DOM 의 차 이 는 무엇 일 까?총 결 은 대략 다음 과 같다.
총 손실=가상 DOM 첨삭 수정+(diff 대비)실제 DOM 차별 화 첨삭 수정+(적은 노드)환류/다시 그리 기; //가상 DOM 사용 손실 계산
빈번 한 조작 을 둘 러 싼 실제 DOM 이 회 류 를 일 으 켜 페이지 의 성능 손실 을 초래 한 것 을 발견 할 수 있다.그러나 프레임 워 크 도 반드시 가상 DOM 을 사용 해 야 하 는 것 은 아니다.잦 은 조작 이 대면 적의 DOM 조작 을 일 으 킬 수 있 는 지 를 보 는 것 이 관건 이다.
과연 가상 DOM 은 어떤 방식 으로 페이지 의 잦 은 DOM 조작 을 줄 였 을 까?DOM Diff 알고리즘 을 알 아야 합 니 다.
DIFF 알고리즘
데이터 가 변 할 때 vue 는 어떻게 보 기 를 업데이트 합 니까?사실은 간단 합 니 다.처음에 실제 DOM 에 따라 가상 DOM 을 생 성 합 니 다.가상 DOM 의 특정한 노드 의 데이터 가 바 뀌 면 새로운 Vnode 를 생 성 한 다음 에 VNode 와 oldVnode 를 비교 하여 서로 다른 부분 을 실제 DOM 에 수정 한 다음 에 oldVnode 의 값 을 Vnode 로 만 듭 니 다.
diff 과정 은 patch 함 수 를 호출 하여 새로운 노드 를 비교 하면 서 실제 DOM 에 패 치(patch)를 하 는 것 입 니 다.
vue 소스 코드 를 대조 하여 해석 하고 핵심 코드 를 붙 이 는 것 은 간단명료 하 게 설명 하 는 데 목적 을 둡 니 다.그렇지 않 으 면 작은 편집 이 자신 이 보기 만 해도 머리 가 큽 니 다 O(∩∩)O
patch
그럼 패 치 는 어떻게 패 치 를 하 는 거 예요?
//patch oldVnode: vnode:
function patch (oldVnode, vnode) {
...
if (sameVnode(oldVnode, vnode)) {
patchVnode(oldVnode, vnode) // , patchVnode
} else {
/* ----- ----- */
const oEl = oldVnode.el // oldVnode
let parentEle = api.parentNode(oEl) //
createEle(vnode) // Vnode
if (parentEle !== null) {
api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl)) //
api.removeChild(parentEle, oldVnode.el) //
oldVnode = null
}
}
...
return vnode
}
//
function sameVnode (a, b) {
return (
a.key === b.key && // key
a.tag === b.tag && //
a.isComment === b.isComment && //
// data,data , onclick , style
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b) // <input> ,type
)
}
위 에서 알 수 있 듯 이 patch 함 수 는 신 구 노드 가 같은 노드 인지 아 닌 지 를 판단 하 는 것 입 니 다.patchVnode
patchVnode 방법 에 도 착 했 으 니 신 구 노드 가 같은 노드 라 는 것 을 설명 한다 면 이 방법 은 어떤 처 리 를 했 습 니까?
function patchVnode (oldVnode, vnode) {
const el = vnode.el = oldVnode.el // DOM
let i, oldCh = oldVnode.children, ch = vnode.children
if (oldVnode === vnode) return // ,
if (oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text) {
// ,
api.setTextContent(el, vnode.text)
}else {
updateEle(el, vnode, oldVnode)
if (oldCh && ch && oldCh !== ch) {
// , updateChildren [ , ]
updateChildren(el, oldCh, ch)
}else if (ch){
// ,
createEle(vnode)
}else if (oldCh){
// ,
api.removeChildren(el)
}
}
}
만약 에 두 노드 가 다 르 면 새로운 노드 로 오래된 노드 를 교체 합 니 다.두 노드 가 같다 면,
updateChildren
코드 가 너무 많아 서 여기 서 먼저 개술 을 하 겠 습 니 다.updateChildren 방법의 핵심:
첫 번 째 단계:
oldStartIdx = A , oldEndIdx = C;
newStartIdx = A , newEndIdx = D;
이때 oldstartIdx 는 new StarIdx 와 일치 하기 때문에 dom 의 A 노드 를 첫 번 째 위치 에 놓 습 니 다.이때 A 는 첫 번 째 위치 에 있 기 때문에 처리 하지 않 습 니 다.이때 실제 DOM 순서:A B C;두 번 째 단계:
oldStartIdx = B , oldEndIdx = C;
newStartIdx = C , oldEndIdx = D;
이때 oldendIdx 는 new StartIdx 와 일치 하여 원래 의 C 노드 를 A 뒤로 이동 합 니 다.이때 실제 DOM 순서:A C B;
세 번 째 단계:
oldStartIdx = C , oldEndIdx = C;
newStartIdx = B , newEndIdx = D;
oldStartIdx++,oldEndIdx--;
oldStartIdx > oldEndIdx
이때 옮 겨 다 니 기 가 끝 났 습 니 다.oldCh 는 이미 옮 겨 다 니 고 있 습 니 다.그러면 나머지 ch 노드 를 자신의 index 에 따라 실제 DOM 에 삽입 하면 됩 니 다.이때 실제 DOM 순서:A C B D;그래서 매 칭 과정 에서 판단 이 끝 나 는 데 두 가지 조건 이 있 습 니 다.
마지막 으로,이 하위 노드 sameVnode 이후 조건 을 만족 시 키 면 patchVnode 를 계속 실행 하고,oldVnode 와 Vnode 의 모든 하위 노드 가 완 성 될 때 까지,모든 패 치 를 다 쳐 서 보기 로 업데이트 합 니 다.
총결산
마지막 으로,한 장의 그림 으로 전체 Diff 과정 을 기억 하고,당신 이 얻 을 수 있 기 를 바 랍 니 다!
달걀
React 는 단순히 기 초 를 배 웠 을 뿐 이 므 로 대비 하여 개술 해 보 겠 습 니 다.
1.React 렌 더 링 메커니즘:React 는 가상 DOM 을 사용 합 니 다.속성 과 상태 가 변 할 때마다 render 함 수 는 서로 다른 요소 트 리 를 되 돌려 주 고 돌아 오 는 요소 트 리 와 지난번 렌 더 링 트 리 의 차 이 를 비교 하여 차이 점 을 업데이트 합 니 다.마지막 으로 실제 DOM 으로 렌 더 링 합 니 다.
2.diff 는 항상 같은 층 으로 비교 합 니 다.만약 에 노드 유형 이 다 르 면 새로운 것 으로 오래된 것 을 교체 합 니 다.만약 에 노드 의 유형 이 같 으 면 그들의 서브 노드 를 비교 하고 순서대로 유추 한다.보통 요소 에 연 결 된 key 값 은 노드 를 비교 하 는 데 사용 되 기 때문에 그 유일 성 을 확보 해 야 합 니 다.보통 배열 아래 표 시 를 key 값 으로 하지 않 습 니 다.배열 요소 가 변화 할 때 index 가 바 뀌 기 때 문 입 니 다.
3.렌 더 링 메커니즘 의 전체 과정 은 업데이트 작업 을 포함 하고 가상 DOM 을 실제 DOM 으로 전환 하기 때문에 전체 렌 더 링 과정 은 Reconciliation 이다.이 과정의 핵심 은 주로 diff 알고리즘 이 고 생명주기 shouldComponentUpdate 함 수 를 이용한다.
Vue 가상 Dom 과 diff 알고리즘 을 알 고 있 는 이 글 은 여기까지 소개 되 었 습 니 다.Vue 가상 Dom 과 diff 알고리즘 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
python 가상 환경 이전 방법2.프로젝트 디 렉 터 리 에 whls 폴 더 를 새로 만 든 다음 가상 환경 cmd 명령 에서 whls 디 렉 터 리 로 전환 합 니 다. pip freeze--all>requirements.txt 명령 을 실행 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.