您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“怎么用js對(duì)象生成dom結(jié)構(gòu)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
首先咱們從起源說(shuō)起,做web開(kāi)發(fā)的時(shí)候,當(dāng)數(shù)據(jù)發(fā)生變化的時(shí)候,我們要去更新dom,從而給前端用戶呈現(xiàn)最新的數(shù)據(jù),流程圖如下:
數(shù)據(jù)更改后直接操作dom,我們舉例來(lái)看一下需求,比方說(shuō)一個(gè)列表,列表下面有一個(gè)點(diǎn)擊加載更多的按鈕:
點(diǎn)擊加載更多,會(huì)發(fā)送一個(gè)ajax請(qǐng)求,請(qǐng)求更多的數(shù)據(jù),然后將數(shù)據(jù)渲染到頁(yè)面,我們一般會(huì)如何做呢,代碼片段如下:
我們看到,每次數(shù)據(jù)更新后,我們借助模板生成html片段,獲取列表的新舊內(nèi)容拼接,這里我們思考一下,就會(huì)發(fā)現(xiàn)已經(jīng)存在的列表信息是不應(yīng)該重新渲染的。
上面的案例先放一邊,先了解一下什么是虛擬dom,簡(jiǎn)單來(lái)說(shuō)就是一句話,用js對(duì)象來(lái)描述dom結(jié)構(gòu),示例如下:
有如下dom結(jié)構(gòu):
<ul id='list'> <li class='item'>item1</li> <li class='item'>item2</li></ul>
用js對(duì)象表示如下:
{
tag: 'ul',
attrs: {
id:'list'
},
children: [
{
tag: 'li',
attrs: {
className: 'item'
},
children: ['item1']
}, {
tag: 'li',
attrs: {
className: 'item'
},
children: ['item2']
}
]
}
既然dom結(jié)構(gòu)可以表示為js對(duì)象,那么根據(jù)js對(duì)象也可以生成dom結(jié)構(gòu)。
再來(lái)看一張圖,這張圖我們將數(shù)據(jù)和ui生成一個(gè)js對(duì)象來(lái)表示dom結(jié)構(gòu)也就是Virtual Dom,然后根據(jù)這個(gè)js對(duì)象(Virtual Dom),來(lái)生成真實(shí)的Dom;
虛擬dom就是上面說(shuō)的js對(duì)象,我們?cè)跀?shù)據(jù)和真實(shí)dom之間,加了一個(gè)中間層,類似夾心餅干。
這樣做有什么好處呢?我們觀察上面的流程,好像比直接操作dom還復(fù)雜,不要急,這里我們還有引入另外一個(gè)概念,diff算法,為什么要引入這個(gè)diff算法呢?
這是因?yàn)樘摂Mdom的渲染機(jī)制,那什么是虛擬dom的渲染機(jī)制呢?
當(dāng)我們更改了數(shù)據(jù)后,并不是我們想的那樣:立即成新的虛擬dom,然后根據(jù)新的虛擬dom渲染成真實(shí)Dom。而是數(shù)據(jù)更改后,在生成新的虛擬dom后,通過(guò)diff算法比較新舊虛擬dom,得出需要重新渲染的部分,然后最小化的更新真實(shí)dom。
流程如下圖:
然后,我們?cè)诳瓷厦娴狞c(diǎn)擊加載更多案例,如果借助了虛擬dom,那么偽代碼可坑就是這樣操作了:
虛擬dom渲染流程用代碼表示如下:
// 1. 構(gòu)建虛擬DOM
var tree = el('div', {'id': 'container'}, [
el('h2', {style: 'color: blue'}, ['simple virtal dom']),
el('p', ['Hello, virtual-dom']),
el('ul', [el('li')])
])
// 2. 通過(guò)虛擬DOM構(gòu)建真正的DOM
var root = tree.render()
document.body.appendChild(root)
// 3. 更改數(shù)據(jù)后生成新的虛擬DOM
var newTree = el('div', {'id': 'container'}, [
el('h2', {style: 'color: red'}, ['simple virtal dom']),
el('p', ['Hello, virtual-dom']),
el('ul', [el('li'), el('li')])
])
// 4. 比較兩棵虛擬DOM樹(shù)的不同
var patches = diff(tree, newTree)
// 5. 在真正的DOM元素上應(yīng)用變更
patch(root, patches)
說(shuō)完虛擬dom,再次提到兩個(gè)最火的前端框架,Vue和react,這兩個(gè)框架都使用了虛擬dom,這兩個(gè)框架所使用的虛擬dom有什么不同呢?
主要是更新虛擬dom的策略不同:
vue中將數(shù)據(jù)維護(hù)成了可觀察的數(shù)據(jù),數(shù)據(jù)的每一項(xiàng)都通過(guò)getter來(lái)收集依賴,然后將依賴轉(zhuǎn)化成watcher保存在閉包中,數(shù)據(jù)修改后,觸發(fā)數(shù)據(jù)的setter方法,然后調(diào)用所有的watcher修改舊的虛擬dom,從而生成新的虛擬dom,然后就是運(yùn)用diff算法 ,得出新舊dom不同,根據(jù)不同更新真實(shí)dom。
而react的更新策略比較粗暴,可以用一個(gè)公式來(lái)表述,virtualDom = h(data),數(shù)據(jù)發(fā)生變化,通過(guò)調(diào)用setState生成新的虛擬dom,(而不是像vue一樣為每個(gè)數(shù)據(jù)社會(huì)setter、getter、watcher),然后對(duì)比新舊dom,得出新舊dom不同,更新真實(shí)dom。但是,react給開(kāi)發(fā)者暴露一個(gè)生命周期函數(shù):shouldcomponentupdate,這個(gè)函數(shù)可以根據(jù)開(kāi)發(fā)者的需求決定數(shù)據(jù)發(fā)生變化決定是否重新渲染。
react是 函數(shù)式組件思想,當(dāng)你 setstate 就會(huì)遍歷,diff 當(dāng)前組件所有的子節(jié)點(diǎn)子組件, 這種方式開(kāi)銷是很大的,要合理使用shouldcomponentupdate。
vue為每個(gè)數(shù)據(jù)設(shè)置setter、getter、watcher,當(dāng)數(shù)據(jù)足夠多時(shí),運(yùn)行效率反倒不如react。
所以在選擇框架時(shí),要衡量一下,如果頁(yè)面數(shù)據(jù)量大,變化多,選react,而如果項(xiàng)目中型,并且想快速開(kāi)發(fā),選vue。
“怎么用js對(duì)象生成dom結(jié)構(gòu)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。