日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解Vue2的diff算法

瀏覽:105日期:2022-10-12 13:21:16
前言

雙端比較算法是vue2.x采用的diff算法,本篇文章只是對雙端比較算法粗略的過程進行了一下分析,具體細節還是得Vue源碼,Vue的源碼在這

過程

假設當前有兩個數組arr1和arr2

let arr1 = [1,2,3,4,5]let arr2 = [4,3,5,1,2]

那么其過程有五步

arr1[0] 和 arr2[0]比較 arr1[ arr1.length-1 ] 和 arr2[ arr2.length-1 ] 比較 arr1[0] 和 arr2[ arr2.length-1 ] 比較 arr1[ arr1.length-1 ] 和 arr2[0] 比較 arr2[0] 和 arr1的每個元素進行比較

每次比較都是從數組的兩端開始比較,如果是首位比較相等,那么比較的開頭索引+1

如果是在末尾比較成功,那么比較的結束索引-1,當開頭索引大于結束索引時說明比較已經結束

拆解過程

let arr1 = [1,2,3,4,5]let arr2 = [4,3,5,1,2]let oldStartIdx = 0 let oldEndIdx = arr1.lenght -1let newStartIdx = 0let newEndIdx = arr2.length -1let oldStartVNode = arr1[oldStartIdx] let oldEndVNode = arr1[oldEndIdx] let newStartVNode = arr2[newStartIdx] let newEndVNode = arr2[newEndIdx]第一輪: 1. 1和4比較不相等 2. 5和2比較不相等 3. 1和2比較不相等 4. 5和4比較不相等 5. 4和舊數組逐一比較,和索引為3的值相等,說明4由索引3變換位置為了0, newStartIdx++ //比較完后,使用u_1表示比較成功的元素 [1,2,3,u_1,5] //arr1 [u_1,3,5,1,2] //arr2第二輪: 1. 1和3比較不相等 2. 5和2比較不相等 3. 1和2比較不相等 4. 5和3比較不相等 5. 3和舊數組逐一比較,和索引為2的值相等,3由索引2變換位置為了0, newStartIdx++ //比較成功后,使用u_2表示比較成功的元素 [1,2,u_2,u_1,5] //arr1 [u_1,u_2,5,1,2] //arr2第三輪: 1. 1和5比較不相等 2. 5和2比較不相等 3. 1和2比較不相等 4. 5和5比較相等,5已經從舊數組oldEndIdx位置移動到了newStartIdx位置,newStartIdx++, oldEndIdx-- 5. 第四步比較成功,進入下一輪 //比較成功后,使用u_3表示比較成功的元素 [1,2,u_2,u_1,u_3] //arr1 [u_1,u_2,u_3,1,2] //arr2第四輪: 1. 1和1比較相等,1已經從舊數組oldStartIdx位置移動到newStartIdx位置,oldStartIdx++,newStartIdx++ 2. 第一步比較成功,進入下一輪 3. 第一步比較成功,進入下一輪 4. 第一步比較成功,進入下一輪 5. 第一步比較成功,進入下一輪 //比較成功后,使用u_4表示比較成功的元素 [u_4,2,u_2,u_1,u_3] //arr1 [u_1,u_2,u_3,u_4,2] //arr2第五輪: 1. 2和2比較相等,1已經從舊數組oldStartIdx位置移動到newStartIdx位置,oldStartIdx++,newStartIdx++ 2. 第一步比較成功,進入下一輪 3. 第一步比較成功,進入下一輪 4. 第一步比較成功,進入下一輪 5. 第一步比較成功,進入下一輪 //比較成功后,使用u_5表示比較成功的元素 [u_4,u_5,u_2,u_1,u_3] //arr1 [u_1,u_2,u_3,u_4,u_5] //arr2

用一個gif圖來表示

詳解Vue2的diff算法

上代碼

function diff(prevChildren, nextChildren) { let oldStartIdx = 0 //舊數組起始索引 let oldEndIdx = prevChildren.length - 1 //舊數組結束索引 let newStartIdx = 0 //新數組其實索引 let newEndIdx = nextChildren.length - 1 //新數組結束索引 let oldStartVNode = prevChildren[oldStartIdx] let oldEndVNode = prevChildren[oldEndIdx] let newStartVNode = nextChildren[newStartIdx] let newEndVNode = nextChildren[newEndIdx] while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { if (!oldStartVNode) { //undefined 時前移一位 oldStartVNode = prevChildren[++oldStartIdx] } else if (!oldEndVNode) { //undefined 時后移一位 oldEndVNode = prevChildren[--oldEndIdx] } else if (oldStartVNode.key === newStartVNode.key ) { //1.開始與開始 oldStartVNode = prevChildren[++oldStartIdx] newStartVNode = nextChildren[++newStartIdx] } else if ( oldEndVNode.key === newEndVNode.key ) { //2.結束與結束 oldEndVNode = prevChildren[--oldEndIdx] newEndVNode = nextChildren[--newEndIdx] } else if (oldStartVNode.key === newEndVNode.key ) { //3.開始與結束 oldStartVNode = prevChildren[++oldStartIdx] newEndVNode = nextChildren[--newEndIdx] } else if (oldEndVNode.key === newStartVNode.key ) { //4.結束與開始 oldEndVNode = prevChildren[--oldEndIdx] newStartVNode = nextChildren[++newStartIdx] } else { //5.新數組開頭元素和舊數組每一個元素對比 const idxInOld = prevChildren.findIndex((node) => {if (node && node.key === newStartVNode.key) { return true} }) if (idxInOld >= 0) {prevChildren[idxInOld] = undefined } else {//newStartVNode是新元素 } newStartVNode = nextChildren[++newStartIdx] } } }diff([1,2,3,4,5],[4,3,5,1,2])

我們發現,上面的算法走完后,如果新舊兩個數組只是順序變化,那么它能完美的diff出差異,但是如果新數組有新增或者刪除的時候就不行了,因此我們在while循環完成后需要找出新增或者刪除的元素,那怎么知道哪些是新增哪些是刪除的元素呢?

在比較的第五步,選取的新數組的第一個元素和舊數組的所有元素逐一對比,這里我們就可以得出了這個數組是否是新增,如果對比相等,那就是位置變換,否則當前元素就是新增的,但是,while循環的條件是oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx,如果是以下情況

let arr1 = [1,2,3,4,5]let arr2 = [1,2,3,4,5,6,7]

因為循環條件的導致,這里會在5次while后就結束了,因此在數組末尾的6和7永遠走不了第五步的插入條件,那如何判斷6和7是新增的呢?我們來觀察一下while循環結束后的索引

//例子1let arr1 = [1,2,3,4,5]let arr2 = [1,2,3,4,5,6,7]//diff后它們的索引為oldStartIdx = 5, oldEndIdx = 4newStartIdx = 5, newEndIdx = 6//例子2let arr1 = [1,2,3,4,5]let arr2 = [4,5,6,7,1,3,2]//diff后它們的索引為oldStartIdx = 3, oldEndIdx = 2newStartIdx = 6, newEndIdx = 5//例子3let arr1 = [1,2,3,4,5]let arr2 = [7,1,3,5,6,4,2]//diff后它們的索引為oldStartIdx = 5, oldEndIdx = 4newStartIdx = 4, newEndIdx = 4//例子4let arr1 = [1,2,3,4,5]let arr2 = [2,4,1,5,7,3,6]//diff后它們的索引為oldStartIdx = 3, oldEndIdx = 2newStartIdx = 6, newEndIdx = 6

我們發現,新增元素的索引和newStartIdx還有newEndIdx是一一對應的

例子1:newStartIdx小于newEndIdx,并且是5和6,而新增元素6對應在arr2的索引為6,新增元素7對應在arr2的索引為7,此時6和7都已經越界出arr1的長度范圍 例子2:newStartIdx是大于newEndIdx,沒有對應關系 例子3:newStartIdx等于newEndIdx,我們發現arr2索引為4的元素正是新增元素6,但是6次時沒有越界出arr1的長度范圍,它剛好在數組的最后一個元素 例子4:newStartIdx等于newEndIdx,arr2中索引為6的值正是新增元素6

那么得出的結論就是,如果在while循環結束后,如果newStartIdx是小于或者等于newEndIdx,那么在newStartIdx和newEndIdx索引之間對應的元素就是新增的元素,并且oldStartIdx總是比oldEndIdx大

上面說完了新增,那如果是刪除元素呢?看例子

//例子1let arr1 = [4,3,5,6,7,2,1]let arr2 = [1,3,5,4,2]//diff后它們的索引為oldStartIdx = 3, oldEndIdx = 4newStartIdx = 3, newStartIdx = 2//例子2let arr1 = [7,2,3,5,6,1,4]let arr2 = [5,1,2,3,4]//diff后它們的索引為oldStartIdx = 0, oldEndIdx = 4newStartIdx = 4, newStartIdx = 3//例子3let arr1 = [1,5,4,2,6,7,3]let arr2 = [4,5,1,2,3]//diff后它們的索引為oldStartIdx = 4, oldEndIdx = 5newStartIdx = 4, newStartIdx = 3

同理新增的觀察套路,發現newStartIdx總是比newStartIdx大,并且需要刪除的元素總是在oldStartIdx和oldEndIdx對應的索引之間,那么我們只需要把oldStartIdx和oldEndIdx的元素刪除即可,那問題來了,像例子2 中oldStartIdx和oldEndIdx索引之間的元素有7,2,3,5,6其中真正需要刪除的只有7和6,這樣子不就誤刪了2,3,5么?關鍵的來了,我們看例子2的2,3,5發現它們走的都是雙端比較算法的第五步,第五步寫的代碼是

const idxInOld = prevChildren.findIndex((node) => { if (node && node.key === newStartVNode.key) { return true } }) if (idxInOld >= 0) { prevChildren[idxInOld] = undefined } else { //newStartVNode是新元素 } newStartVNode = nextChildren[++newStartIdx]

如果idxInOld>0說明在舊數組中找到了,那么我們將preChildren[idxInOld]設置為undefined,也就是說2,3,5經過diff算法后,它們在arr1中的值已經被替換為了undefined,這里也是就為什么在diff算法開始需要判斷!oldStartVNode和!oldEndVnode的原因了,下面我們完善代碼

function diff(prevChildren, nextChildren) { let oldStartIdx = 0 //舊數組起始索引 let oldEndIdx = prevChildren.length - 1 //舊數組結束索引 let newStartIdx = 0 //新數組其實索引 let newEndIdx = nextChildren.length - 1 //新數組結束索引 let oldStartVNode = prevChildren[oldStartIdx] let oldEndVNode = prevChildren[oldEndIdx] let newStartVNode = nextChildren[newStartIdx] let newEndVNode = nextChildren[newEndIdx] while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { if (!oldStartVNode) { //undefined 時前移一位 oldStartVNode = prevChildren[++oldStartIdx] } else if (!oldEndVNode) { //undefined 時后移一位 oldEndVNode = prevChildren[--oldEndIdx] } else if (oldStartVNode.key === newStartVNode.key ) { //1.開始與開始 oldStartVNode = prevChildren[++oldStartIdx] newStartVNode = nextChildren[++newStartIdx] } else if ( oldEndVNode.key === newEndVNode.key ) { //2.結束與結束 oldEndVNode = prevChildren[--oldEndIdx] newEndVNode = nextChildren[--newEndIdx] } else if (oldStartVNode.key === newEndVNode.key ) { //3.開始與結束 oldStartVNode = prevChildren[++oldStartIdx] newEndVNode = nextChildren[--newEndIdx] } else if (oldEndVNode.key === newStartVNode.key ) { //4.結束與開始 oldEndVNode = prevChildren[--oldEndIdx] newStartVNode = nextChildren[++newStartIdx] } else { //5.新數組開頭元素和舊數組每一個元素對比 const idxInOld = prevChildren.findIndex((node) => {if (node && node.key === newStartVNode.key) { return true} }) if (idxInOld >= 0) {prevChildren[idxInOld] = undefined } else {//newStartVNode是新元素 } newStartVNode = nextChildren[++newStartIdx] } } if (oldStartIdx > oldEndIdx) { for (; newStartIdx <= newEndIdx; ++newStartIdx) { //新增內容 let vnode = nextChildren[newStartIdx] } } else if (newStartIdx > newEndIdx) { for (let i = oldStartIdx; i <= oldEndIdx; i++) { / /刪除內容 } }}diff([1,2,3,4,5],[4,3,5,1,2])

接下來我們使用兩個gif圖來表示一下diff過程

1.新增元素

詳解Vue2的diff算法

2.減少元素

詳解Vue2的diff算法

以上就是詳解Vue2的diff算法的詳細內容,更多關于Vue2的diff算法的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品丝袜在线播放| 久久久久免费av| 亚洲大全视频| 成人免费一区| 久久精品国产久精国产爱| 88久久精品| 日本午夜精品一区二区三区电影 | 欧美日韩中文字幕一区二区三区| 国产精品美女久久久久久不卡| 亚洲免费观看高清完整版在线观| 老牛影视一区二区三区| 玖玖玖国产精品| 蜜臀久久久99精品久久久久久| 亚洲一级在线| 日韩网站在线| 免费的成人av| 亚洲综合五月| 日韩精品1区2区3区| 日韩一二三区在线观看| 日韩高清成人在线| 国产欧美日韩一级| 精品国产乱码久久久久久樱花| 狠狠久久伊人| 欧美视频二区| 日韩av一区二区在线影视| 色狠狠一区二区三区| 亚洲免费福利一区| 日韩国产在线一| 97精品国产99久久久久久免费| 国产成人免费精品| 97精品国产一区二区三区| 精品亚洲美女网站| 亚洲少妇自拍| 日韩中文字幕一区二区高清99| 国产精品亚洲综合色区韩国| 中文字幕在线高清| 国产高清久久| 亚洲三区欧美一区国产二区| 亚洲午夜一级| 亚洲精品一级二级三级| 国产a亚洲精品| 国产欧美日韩影院| 日韩成人a**站| 国产精品88久久久久久| 老司机精品久久| 欧美亚洲二区| 四虎8848精品成人免费网站 | 91精品蜜臀一区二区三区在线| 欧美影院三区| 亚洲一区二区日韩| 日韩va亚洲va欧美va久久| 福利片在线一区二区| 成人在线超碰| 91精品国产自产在线观看永久∴| 欧美不卡高清| 蜜臀精品久久久久久蜜臀| 欧美亚洲自偷自偷| 麻豆91精品视频| 久久久久久久久99精品大| 亚洲深夜av| 欧美日韩夜夜| 久久久777| 亚洲三级网址| 久久99偷拍| 国产麻豆久久| 亚洲一卡久久| 国产日韩免费| 国产精品久久久免费| 毛片在线网站| 欧美日韩国产亚洲一区| 成人综合一区| 精品三级av| 国产精品一区三区在线观看| 福利视频一区| 一二三区精品| 精品国产亚洲一区二区三区大结局| 伊人久久成人| 国产精品男女| 国产一区二区三区自拍| 亚洲毛片在线| 日本在线高清| 亚洲人妖在线| 911亚洲精品| 亚洲成人av观看| 亚洲日本免费电影| 国产精品免费大片| 免费毛片在线不卡| 欧美片网站免费| 久久伦理在线| 91成人小视频| 欧美高清不卡| 国产精品一区二区精品视频观看| 欧美aa在线观看| 午夜久久av | 欧美日韩一区二区三区视频播放| 中文字幕亚洲在线观看| 在线中文字幕播放| 青青国产精品| 欧美色图国产精品| 国产丝袜一区| 欧美在线观看视频一区| 欧美激情三区| 日韩中文欧美在线| 激情国产在线| 不卡在线一区二区| 亚洲三级av| xxxxx性欧美特大| 蜜桃一区二区三区| 蜜桃av.网站在线观看| 在线一区视频| 久久久久久自在自线| 日韩和欧美一区二区三区| 波多野结衣一区| 久久精品国产网站| 中文字幕av一区二区三区四区| 电影天堂国产精品| 国产精品一区二区美女视频免费看 | 久久久久伊人| 亚洲三级国产| 亚洲欧洲美洲av| 手机在线电影一区| 国产精品日本一区二区三区在线 | 夜夜嗨网站十八久久 | 日本不卡在线视频| 99在线精品免费视频九九视| 高清一区二区| 精品理论电影在线| 国产调教精品| 日本不卡视频一二三区| 免费污视频在线一区| 老司机精品视频网| 美女久久一区| 欧美.日韩.国产.一区.二区| 久久一区精品| 国产乱论精品| 91成人精品在线| 日韩精品亚洲专区在线观看| 亚洲欧美久久久| 欧洲毛片在线视频免费观看| 国产精品久久久久久久久妇女| 国产精品国码视频| 国产日本久久| 青草综合视频| 亚洲高清影视| 黄色免费成人| 极品日韩av| 日韩免费看片| 国产一区二区三区四区五区传媒| 国产精品手机在线播放| 91九色综合| 啪啪亚洲精品| 清纯唯美亚洲综合一区| 日韩精品欧美大片| 蜜臀av一区二区三区| 视频一区二区中文字幕| 日韩在线观看一区| 日本特黄久久久高潮| 国产免费久久| 国产视频网站一区二区三区| 日本精品久久| 国产日韩免费| 97精品国产99久久久久久免费| 婷婷五月色综合香五月| 亚洲精品乱码日韩| 日韩在线观看一区二区三区| 亚洲影院天堂中文av色| 最新国产精品视频| 日韩亚洲精品在线观看| 亚洲毛片视频| 蜜桃久久av一区| 亚洲日产国产精品| 日韩欧美中文字幕一区二区三区 | av免费不卡国产观看| 日韩精品1区| 红杏一区二区三区| 日韩久久精品| 国产一区清纯| 亚洲欧美高清| 日韩高清二区| 国产亚洲一区二区三区啪| yellow在线观看网址| 中文字幕高清在线播放| 久久中文字幕av| 日韩制服丝袜先锋影音| 日韩国产91| 精品国产亚洲一区二区三区| 亚洲黄色中文字幕| 国产国产精品| 免费观看日韩电影| 亚洲毛片在线免费| 美女久久99| 五月天久久777| 亚洲精品麻豆| 日韩精品免费视频人成| 精品一区二区三区视频在线播放 | 久久香蕉国产| 亚洲涩涩av| 老鸭窝一区二区久久精品| 欧洲亚洲一区二区三区| 老司机精品久久|