當(dāng)前位置:
首頁(yè) >
前端技术
> javascript
>内容正文
javascript
javascript --- 将DOM结构转换成虚拟DOM 虚拟DOM转换成真实的DOM结构
生活随笔
收集整理的這篇文章主要介紹了
javascript --- 将DOM结构转换成虚拟DOM 虚拟DOM转换成真实的DOM结构
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
虛擬DOM的實(shí)現(xiàn)
使用虛擬DOM的原因: 減少回流與重繪
將DOM結(jié)構(gòu)轉(zhuǎn)換成對(duì)象保存到內(nèi)存中
<img /> => { tag: 'img'}
文本節(jié)點(diǎn) => { tag: undefined, value: '文本節(jié)點(diǎn)' }
<img title="1" class="c" /> => { tag: 'img', data: { title = "1", class="c" } }
<div><img /></div> => { tag: 'div', children: [{ tag: 'div' }]}
根據(jù)上面可以寫出虛擬DOM的數(shù)據(jù)結(jié)構(gòu)
class VNode {constructor(tag, data, value, type) {this.tag = tag && tag.toLowerCase()this.data = datathis.value = valuethis.type = typethis.children = []}appendChild(vnode){this.children.push(vnode)} }可能用到的基礎(chǔ)知識(shí)
- 判斷元素的節(jié)點(diǎn)類型: node.nodeType
- 獲取元素類型的標(biāo)簽名和屬性 && 屬性中具體的鍵值對(duì),保存在一個(gè)對(duì)象中
- 獲取當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)
算法思路
- 使用document.querySelector獲取要轉(zhuǎn)換成虛擬DOM的模板
- 使用nodeType方法來(lái)獲取是元素類型還是文本類型
- 若是元素類型
- 使用nodeName獲取標(biāo)簽名
- 使用attributes獲取屬性名,并將具體的屬性保存到一個(gè)對(duì)象_attrObj中
- 創(chuàng)建虛擬DOM節(jié)點(diǎn)
- 考慮元素類型是否有子節(jié)點(diǎn),使用遞歸,將子節(jié)點(diǎn)的虛擬DOM存入其中
- 若是文本類型
- 直接創(chuàng)建虛擬DOM,不需要考慮子節(jié)點(diǎn)的問(wèn)題
以上寫了虛擬DOM的數(shù)據(jù)結(jié)構(gòu),以及使用getVNode方法將真實(shí)DOM結(jié)構(gòu)轉(zhuǎn)換成虛擬DOM,下面開(kāi)始逐步實(shí)現(xiàn)getVNode方法
- 判斷節(jié)點(diǎn)類型,并返回虛擬DOM
- 下面根據(jù)元素類型和文本類型分別創(chuàng)建虛擬DOM
總體代碼
class VNode {constructor(tag, data, value, type) {this.tag = tag && tag.toLowerCase()this.data = datathis.value = valuethis.type = typethis.children = []}appendChild(vnode){this.children.push(vnode)} }function getVNode(node) {let nodeType = node.nodeTypelet _vnode = nullif (nodeType == 1) {let tag = node.nodeNamelet attrs = node.attributeslet _data = {}for (let i = 0, len = attrs.length; i < len; i++) {_data[attrs[i].nodeName] = attrs[i].nodeValue}_vnode = new VNode(tag, _data, undefined, nodeType)let childNodes = node.childNodesfor (let i = 0, len = childNodes.length; i < len; i++) {_vnode.appendChild(getVNode(childNodes[i]))}} else if (nodeType == 3) {_vnode = new VNode(undefined, undefined, node.nodeValue, nodeType)}return _vnode }let root = document.querySelector('#root') let vroot = getVNode(root) console.log(vroot)將虛擬DOM轉(zhuǎn)換成真實(shí)的DOM結(jié)構(gòu)
此過(guò)程就是上面的反過(guò)程
可能用到的知識(shí)點(diǎn)
- 創(chuàng)建文本節(jié)點(diǎn)
- 創(chuàng)建元素節(jié)點(diǎn)
- 給元素節(jié)點(diǎn)添加屬性
- 給元素節(jié)點(diǎn)添加子節(jié)點(diǎn)
算法思路
- 虛擬DOM的結(jié)構(gòu)中,元素的節(jié)點(diǎn)類型存儲(chǔ)在type中,根據(jù)type可以判斷出是文本節(jié)點(diǎn)還是元素節(jié)點(diǎn)
- 若為文本節(jié)點(diǎn),直接返回一個(gè)文本節(jié)點(diǎn)return document.createTextNode(value)
- 若為元素節(jié)點(diǎn)
- 創(chuàng)建一個(gè)node節(jié)點(diǎn):_node = document.createElement(tag)
- 遍歷虛擬DOM中的data屬性,將其中的值賦給node節(jié)點(diǎn)
- 給當(dāng)前節(jié)點(diǎn)添加子節(jié)點(diǎn)
具體實(shí)現(xiàn)
function parseVNode(vnode){let type = vnode.typelet _node = nullif(type == 3){return document.createTextNode(vnode.value)} else if (type == 1){_node = document.createElement(vnode.tag)let data = vnode.datalet attrName,attrValueObject.keys(data).forEach(key=>{attrName = keyattrValue = data[key]_node.setAttribute(attrName, attrValue)})// 考慮子元素let children = vnode.childrenchildren.forEach( subvnode =>{_node.appendChild(parseVNode(subvnode))})}return _node }驗(yàn)證:
let root = querySelector('#root') let vroot = getVNode(root) console.log(vroot) let root1 = parseVNode(vroot) console.log(root1)總結(jié)
以上是生活随笔為你收集整理的javascript --- 将DOM结构转换成虚拟DOM 虚拟DOM转换成真实的DOM结构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: fluidsim元件库下载_FluidS
- 下一篇: gradle idea java ssm