為什麼要實現一個React?如果你進來看了這篇文章,相信你我的想法是一致的,為了更好的理解和使用React。這一篇是這個文章系列的第一篇,主要說下實現React之前需要掌握和明白的地方,不單單是介紹,請耐心看完。這個系列需要足夠的耐心去看,靜下心來才能有更大的收穫。本系列文章參考dialact系列文章,你可以直接去看dialact,它也足夠精簡。這個系列中我會調整部分結構來幫助理解。
預備知識
在React的實現中,有幾種寫法需要了解。
為dom元素新增Attribute
var dom = document.getElmentById('root');
dom['className'] = 'container'
dom['style'] = 'background-color: red';
複製程式碼
我們這裡使用直接賦值的方法,而不是使用setAttribute
來給dom新增Attribute,是為了保證只有有效的Attribute
才能被賦值。這裡涉及到attribute
和property
的區別。
attribute和property的區別
attribute
描述xml中的附加值如
<apple name='apple'></apple>
複製程式碼
這裡的name
就是attribute
,property
在js中描述的是物件的屬性如
var person = { name: 'chris' }
複製程式碼
這裡的name
是property
。
對於dom元素來說,它是一個HTMLElement
型別的物件,它有很多property
,在其property
中有一個attributes
屬性,該屬性是NameNodeMap
型別,用來儲存html展示的attributes
。
當我們使用setAttribute
函式時,會直接為attributes
賦值,不論其名稱如何。而如果我們使用dom['property'] = value
的形式的時候,它會根據名稱尋找和attributes
之間的對應關係,如果有對應則在賦值的同時為dom
新增attribute
,如果沒有則只新增property
而不會新增attribute
。
property
和attribute
之間的物件關係根據不同的元素型別來確定,同時對應名稱也不是一定相同,如
// property => attribute
style => style
className => class
htmlFor => html
複製程式碼
其他要用到的方法
// 為元素繫結事件
dom.addEventListener('click', function() {});
// 為文字節點賦值
dom['nodeValue'] = value;
// 尋找節點
var dom = document.getElementById('root');
// 建立節點
var dom = document.createElement('div');
// 建立文字節點
var dom = document.createTextNode('');
複製程式碼
jsx
jsx的本質是一個語法糖,例如有如下jsx語法
<div className="container">
<h1>hello world</h1>
</div>
複製程式碼
在React中會被解析成如下形式:
React.createElement(
'div',
{ className: 'container' },
React.createElement(
h1,
null,
"hello world"
)
)
複製程式碼
這個轉換我們可以藉助babel-plugin-transform-react-jsx來幫助我們實現,我們所需要做的就是實現React.createElement
。
diff
由於操作dom要付出的代價很大,React最大限度的來利用已經生成的dom,避免重複渲染。React中用到了虛擬dom的概念,它其實就是一個物件,類似於我們上面jsx中寫到的
{
type: 'h1',
children: ['hello world']
}
複製程式碼
實際的React中更加複雜,配合diff演算法可以減少dom操作。傳統比較兩棵樹的演算法是O(n^3)
,React有兩個假設:
- 不同型別的節點會產生不同的樹
- 開發者能夠通過賦值
key
屬性來區分列表中不同的節點
在這兩個假設的基礎上,React只需要比較兩棵dom樹中同一層對應的節點就可以,將演算法複雜度降低到O(n)
,同時能覆蓋到絕大部分的情況,這種diff演算法在React中被稱作Reconciliation
下一篇,我們開始實現我們自己的React,先進行節點建立和渲染。接下來我會持續更新,這是github原文地址,歡迎star,歡迎watch。
實現React系列列表: