Written in front, note from www.bilibili.com/video/BV1iX… Please correct any questions if you have any
As we said, the Diff algorithm follows:
New before, new after, old before, old after, new before, new before, old afterCopy the code
In order to query hits
Export default function updataChildren(parentElm,oldCh,newCh){console.log(' I am updataChildren', oldCh,newCh) // Let oldStartIdx = 0; // let newStartIdx = 0; // let oldEndIdx = oldch.length -1; // let newEndIdx = newch.length -1; // Let oldStartVnode = oldCh[0] let oldEndVnode = oldCh[oldEndIdx] // Let newStartVnode = newCh[0] let newEndVnode = newCh[newEndIdx] \ }Copy the code
updateChildren.js:
import patchVnode from '.. /patchVnode.js' import createElement from '.. /createElement.js' function checkSameVnode(a, b) { return a.sel == b.sel && a.key == b.key } export default function updataChildren(parentElm, oldCh, NewCh) {// console.log(' I am updataChildren',parentElm,oldCh,newCh) // let newStartIdx = 0; // let oldEndIdx = oldch.length - 1; // let newEndIdx = newch.length - 1; // Let oldStartVnode = oldCh[0] let oldEndVnode = oldCh[oldEndIdx] // Let newStartVnode = newCh[0] NewEndVnode = newCh[newEndIdx] let keyMap = null // start big while while (oldStartIdx <= oldEndIdx && newStartIdx <= NewEndIdx) {/ / if here is in dealing with the virtual node is identified as the undefined if (oldStartVnode = = null | | oldCh [oldStartIdx] = = undefined) { oldStartVnode = oldCh[++oldStartIdx] } else if (oldEndVnode == null || oldCh[oldEndIdx] == undefined) { oldEndVnode = oldCh[--oldEndIdx] } else if (newStartVnode == null || newCh[newStartIdx] == undefined) { newStartVnode = newCh[++newStartIdx] } else if (newEndVnode == null || newCh[newEndIdx] == undefined) { newEndVnode = new [--newEndIdx] } else if (checkSameVnode(oldStartVnode, NewStartVnode)) {console.log('1 new before old before ') // patchVnode(oldStartVnode, newStartVnode) // OldStartVnode = oldCh[++oldStartIdx] newStartVnode = newCh[++newStartIdx If (checkSameVnode(newEndVnode, oldEndVnode)) {console.log('2 new after old after ') patchVnode(oldEndVnode, NewEndVnode) oldEndVnode = oldCh[--oldEndIdx] newEndVnode = newCh[--newEndIdx (checkSameVnode(newEndVnode, oldStartVnode)) {console.log('3 new after old before ') patchVnode(oldStartVnode, Parentelm.insertbefore (oldStartvNode.elm, oldEndVnode.elm.nextSibling) oldStartVnode = oldCh[++oldStartIdx] newEndVnode = newCh[--newEndIdx] // // How to move the node to the real DOM?? Just insert a node that's already in the DOM tree, } else if (checkSameVnode(newStartVnode, oldEndVnode)) {// New before old after console.log('4 new before old after ') \ patchVnode(newStartVnode, oldEndVnode) parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm) oldEndVnode = oldCh[--oldEndIdx] newStartVnode = newCh[++newStartIdx] \ // } else {// Four hits are not found, is the last logic of the current diff algorithm, is also the most complex diff algorithm in the most complex case !!!! // Find the map of the key, make a map of the keyMap, so that you do not have to iterate over the old object every time. For (let I = oldStartIdx; for (let I = oldStartIdx; i <= oldEndIdx; i++) { const key = oldCh[i].key if (key ! = undefined) { keyMap[key] = i } } } console.log(1111,keyMap, NewStartVnode) // Find the location of the current newStartIdx mapping in keyMap const idxInOld = keyMap[newStartvNode.key] console.log(idxInOld) // If idxInOld is undefined, it means that the node is completely new and does not exist in the old node. If (idxInOld == undefined) {parentelm. insertBefore(createElement(newStartVnode), oldStartvNode.elm)} else {// If it's not a brand new node, // debugger const elmToMove = oldCh[idxInOld] console.log(1, ElmToMove) // if(elmtomove.elm.nodeType == 1){patchVnode(elmToMove, newStartVnode) // Set this node to undefined, OldCh [idxInOld] = undefined parentelm.insertbefore () parentelm.insertbefore (elmtomove.elm, NewStartVnode = newCh[++newStartIdx] // newStartIdx++}} // old To see if there are any nodes left in new, If (newStartIdx <= newEndIdx) {// add console.log('new has nodes left ') // debugger // const before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm // console.log(before) for (let i = newStartIdx; i <= newEndIdx; I ++) {// newCh[I] is just a virtual node at this point, not yet called a real DOM, Parentelm.insertbefore (createElement(newCh[I])), OldCh [oldStartIdx].elm) // insertBefore AppendChild ()}} else if (oldStartIdx <= oldEndIdx) {// End of new loop, old and delete remaining nodes in old. You can't delete the end, that is to say, in this case, you can only delete the node whose end is matched, and if you can't match the end, you can't match the end, and this is an infinite loop, Console. log('old has nodes left ') // Delete the nodes between oldStartIdx and oldEndIdx in batches for (let I = oldStartIdx; i <= oldEndIdx; i++) { if (oldCh[i]) { parentElm.removeChild(oldCh[i].elm) } } } }Copy the code
This section is so hard. Also encountered a lot of bugs, will be sorted out later: 1. Remaining items ===> Add/delete logic