先介紹乙個概念virtual dom,我猜大家或多或少都應該知道什麼是virtual dom吧,簡單來說就是用js來模擬dom中的結點。
下面就是乙個virtual dom的結構,包含了標籤名,擁有的屬性,孩子結點,render函式
class element ;
this.children = children || ;
} render
() }複製**
建立一棵個virtual dom tree && 渲染/**
**///根據上面結構可以用一下方式建立一棵 virtual dom tree
let ul = element('ul', , [
element('li', , ['txt_a']),
element('li', , ['txt_b'])
]);//ul 就是一棵個virtual dom tree
let uldom = ul.render();//生成真實dom
複製**
以上就是virtual dom tree如何被轉換成真實dom並新增到網頁中的過程,再這個過程中我把render函式給省略,只是為了讓你們先了解原理,具體實現可以以後再深究。我學乙個東西的時候,習慣是先把整體原理弄清楚,再去深入學習相關的知識。
在介紹diff演算法之前,再次宣告我只會列舉diff演算法中會用到的函式,並串聯它們之間的關係並不會給出具體實現的**
介紹diff演算法是進行虛擬節點element的對比,並返回乙個pathchs物件,用來儲存兩個節點不同的地方,最後用pathchs記錄的訊息去區域性更新dom。
兩個樹如果完全比較的話需要時間複雜度為o(n^3),如果對o(n^3)不太清楚的話建議去網上搜尋資料。而在diff演算法中因為考慮效率的問題,只會對同層級元素比較,時間複雜度則為o(n),說白了就是深度遍歷,並比較同層級的節點。
diff只需下面兩句**
let pathchs = diff(oldtree, newtree);//獲取兩棵virtual dom tree 差異
patch(uldom, pathchs);//找到對應的真實dom,進行部分渲染
複製**
diff中所用到的函式//深度遍歷樹,將需要做變更操作的取出來
//區域性更新 dom
function patch(node,pathchs)
// diff 入口,比較新舊兩棵樹的差異
function diff (oldtree, newtree) // 記錄每個節點差異的補丁
dfs(oldtree, newtree, index, patches)
return patches;
}/**
* dfs 深度遍歷查詢節點差異
* @param oldnode - 舊虛擬dom樹
* @param newnode - 新虛擬dom樹
* @param index - 當前所在樹的第幾層
* @param patches - 記錄節點差異
*/function dfs (oldnode, newnode, index, patches)else
if (istxt(oldnode) && istxt(newnode)) )
//如果發現文字不同,currentpatch會記錄乙個差異
}else
if(oldnode.tagname === newnode.tagname && oldnode.key === newnode.key))
}// 遞迴遍歷子節點,並對子節點進行diff比較
diffchildren(oldnode.children, newnode.children, index, patches)
}else)
}//如果有差異則記錄到當前層去
if (currentpatch.length) else
}}//判斷兩個節點的屬性差異
function diffattrs(oldnode, newnode);//記錄差異
let count = 0;//記錄差異的條數
/****略
判斷兩個節點的屬性差異的**就略了,
讓你們知道這裡的**就是判斷兩個節點的屬性有哪些差異,
如果有差異就記錄在attrspatches這個物件中,並把它返回
**/if(0 == count)else
}//判斷孩子節點
function diffchildren(oldchild, newchild, index, patches) = listdiff(oldchild, newchild, index, patches);
if (changes.length) else
}// **略
//遍歷當前陣列
oldchild && oldchild.foreach((item, i) => )
}//判斷oldnodelist, newnodelist 節點的位置差,主要是為了判斷哪些節點被移動、刪除、新增。
function listdiff(oldnodelist, newnodelist, index);
}複製**
如果大家對函式之間的呼叫還不明白的話可以看下面的圖
virtual dom 演算法的實現也就是以下三步
原環套原環
今天在除錯兄弟的程式的時候發現了乙個問題,就是在組合資料的時候,有些時候可以成功,有些時候失敗,感覺十分奇怪。功能大概是這樣的,就是在一棵樹上掛資料,所有的節點都可以有資料,不只是葉子的,在組合資料的時候,可以從任意節點取資料,但是不能是重複的資料。資料可能出現的情況如圖a b c所示,圖a是沒有干...
MongoDB writeConcern原理解析
mongodb支援客戶端靈活配置寫入策略 writeconcern 以滿足不同場景的需求。db.collection.insert mongodb支援的writeconncern選項如下 w 資料寫入到number個節點才向用客戶端確認 j 寫入操作的journal持久化後才向客戶端確認 wtime...
LinkedBlockingQueue原理分析
linkedblockingqueue也是乙個阻塞佇列,相比於arrayblockingqueue,他的底層是使用鍊錶實現的,而且是乙個可有界可無界的佇列,在生產和消費的時候使用了兩把鎖,提高併發,是乙個高效的阻塞佇列,下面就分析一下這個佇列的原始碼。鍊錶節點定義 static class node...