新旧子节点前面几组 type 都相同,只有后面的有区别的 diff 算法
function patchChildren ( n1 , n2 , container ) {
///...
const oldChildren = n1 . children ;
const newChildren = n2 . children ;
const oldLen = oldChildren . length ;
const newLen = newChildren . length ;
const commonLen = Math . min ( oldLen , newLen ) ;
for ( let i = 0 ; i < commonLen ; i ++ ) {
patch ( oldChildren [ i ] , newChildren [ i ] ) ;
}
if ( newLen > oldLen ) {
patch ( null , newChildren [ i ] , container ) ;
} else if ( newLen < oldLen ) {
for ( let i = commonLen ; i < oldLen ; i ++ ) {
umount ( oldChildren [ i ] ) ;
}
}
}
function patchChildren ( n1 , n2 , children ) {
///...
const oldChildren = n1 . children ;
const newChildren = n2 . children ;
for ( let i = 0 ; i < newChildren . length ; i ++ ) {
const newVNode = oldChildren [ i ] ;
for ( let j = 0 ; j < oldChildren . length ; j ++ ) {
const oldVNode = newChildren [ j ] ;
if ( newVNode . key === oldVNode . key ) {
patch ( oldVNode , newVNode ) ;
break ;
}
}
}
}
// 判断是否需要移动
function patchChildren ( n1 , n2 , children ) {
///...
const oldChildren = n1 . children ;
const newChildren = n2 . children ;
let lastIndex = 0 ;
for ( let i = 0 ; i < newChildren . length ; i ++ ) {
const newVNode = oldChildren [ i ] ;
for ( let j = 0 ; j < oldChildren . length ; j ++ ) {
const oldVNode = newChildren [ j ] ;
if ( newVNode . key === oldVNode . key ) {
patch ( oldVNode , newVNode ) ;
if ( j < lastIndex ) {
// 需要移动
} else if ( j > lastIndex ) {
lastIndex = j ;
}
break ;
}
}
}
}
function patchChildren ( n1 , n2 , container ) {
///...
if ( j < lastIndex ) {
const prevVNode = newChildren [ i - 1 ] ;
if ( prevVNode ) {
const anchor = prevVNode . el . nextSibling ;
insert ( newVNode . el , container , anchor ) ;
}
}
}
function patchChildren ( n1 , n2 , container ) {
if ( typeof n2 . children === "string" ) {
//
} else if ( Array . isArray ( n2 . children ) ) {
const oldChildren = n1 . children ;
const newChildren = n2 . children ;
let lastIndex = 0 ;
for ( let i = 0 ; i < newChildren . length ; i ++ ) {
const newVNode = newChildren [ i ] ;
let j = 0 ;
let find = false ;
for ( ; j < oldChildren ; j ++ ) {
const oldVNode = oldChildren [ j ] ;
const has = newChildren . find ( ( vnode ) => vnode . key === oldVNode . key ) ;
if ( ! has ) {
unmount ( oldVNode ) ;
}
if ( j < lastIndex ) {
if ( newVNode . key === oldVNode . key ) {
find = true ;
patch ( oldVNode , newVNode , container ) ;
if ( j < lastIndex ) {
const prevVNode = newChildren [ j - 1 ] ;
if ( prevVNode ) {
const anchor = prevVNode . el . nextSibing ;
insert ( newVNode . el , container , anchor ) ;
}
}
}
} else {
lastIndex = j ;
}
break ;
}
}
if ( ! find ) {
const prevVNode = newChildren [ i - 1 ] ;
if ( prevVNode ) {
const anchor = prevVNode . el . nextSibing ;
} else {
anchor = container . firstChild ;
}
patch ( null , newVNode , container , anchor ) ;
}
}
}