生成dom的過程
-
由vue模板生成虛擬dom
-
虛擬dom轉換成真實dom渲染到html頁面
代碼實現
- 要實現的真實dom
<div id="box">
<p class="red">hello<span>world</span></p>
<hr />
</div>
- 虛擬dom (在此省略template模板編譯的過程,直接手動創建)
let vNode = h('div', {id: 'box'}, [
h('p', {class: 'red'}, [
h('span', {}, [h('', {}, ['world'])])
]),
h('hr', {}, [])
])
結果:
生成虛擬dom的h函數的實現
function h(tagName, props = {}, children = []) { //生成虛擬dom
if (!(this instanceof h)) {
return new h(tagName, props, children)
}
this.tagName = tagName //添加屬性
this.props = props
this.children = children
// this.key = key++
}
- 將虛擬dom轉化成正式的dom
function createElements(vNode) { //創建成實際的dom
let el
if (vNode.tagName){ //為標簽就創建標簽節點
el = document.createElement(vNode.tagName)
} else {//否則創建文本節點
el = document.createTextNode(vNode.children)
}
for (attr in vNode.props) { //遍歷屬性創建屬性
el.setAttribute(attr, vNode.props[attr])
}
vNode.children.forEach((item) => { //
// console.log(item)
if (item.children) {//如果子節點不為空就遞歸創建
let children = createElements(item)
el.appendChild(children) //將每次創建的子節添加到父節點中
}
})
return el
}
- 將真實dom渲染到頁面指定容器中,寫一個簡單render函數
let vDom = createElements(vNode)
function render(vDom, dom) { //將創建的dom添加到指定的容器中
document.querySelector(dom).appendChild(vDom)
}
render(vDom, '#app')
- 最終結果