閒的沒事兒,研究了一下虛擬DOM渲染相關的東西,後來本身試着用ES6實現了一下。javascript
github:github.com/Huoshendame…java
題目:給定一個樹形結構的JSON,實現VDOM
let demoNode = {
tagName: 'ul',
props: {'class':'list'},
children: [
{
tagName: 'li',
props: {'class':'item'},
children: ['Three Kindom']
},
{
tagName: 'li',
props: {'class':'item'},
children: ['START GAME']
}
]}複製代碼
思路:
1.定義一個父類,將樹結構裏面能夠生成DOM的元素實例化爲子類。git
2.定義父類的render函數,來將VDOM渲染成真實的DOM。github
---------------------------------靚麗的分割線----------------------------------------------bash
接下來咱們用代碼一步一步實現它。app
首先定義一個Element類,而後定義他的構造函數dom
class Element {
constructor(props){
}
}複製代碼
接下來咱們定義他的初始化方法,也就是實例化爲子類的方法。函數
( 這裏可能有人會問爲何要實例化爲子類?)ui
( 由於子類也要用到render函數來渲染本身,因此要經過二叉樹深度優先的遍歷方式去把 「子類-->子類的子類-->最後一個子類「 都要實例化爲Element的子類。經過__proto__去繼承父類的方法。也就是render方法。)this
class Element {
constructor(props){
this.init(props)
}
init(props){
this.tagName = props.tagName || ''
this.props = props.props || {}
this.children = props.children || []
let _child = []
this.children = this.children.map((child) => {
if(typeof child == "object" ){
child = new Element(child)
}
return child
})
}
}複製代碼
再來咱們定義他的render方法。
1.建立當前節點
2.將屬性賦值到當前節點上
3.遍歷他的子節點。
(1)若是是Element的子類,則證實是能夠生成DOM的VDOM。而後去遞歸render方法去建立以及初始化他。
(2)若是不是Element的子類,則證實是最後節點的值。直接賦值便可。
class Element(){
constructor(props){...}
init(props){...}
render(){
let ele = document.createElement(this.tagName)
for (let propsName in this.props){
ele.setAttribute(propsName, this.props[propsName])
}
this.children.forEach(function(item ,index){
let childELement = null
if( item instanceof Element){
childELement = item.render()
}else{
childELement = document.createTextNode(item)
}
ele.appendChild(childELement)
})
return ele
}}複製代碼
經過定義以上的類,咱們的虛擬DOM渲染功能就作完了。能夠運行試一下。
let demoElement = new Element(demoNode);
document.body.appendChild(demoElement.render());複製代碼