成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Virtual DOM的歷史和未來

譯文
開發(fā) 前端
Virtual DOM最初是由React的作者開創(chuàng)的,目的是使聲明式UI的渲染速度更快。為了理解為什么聲明式UI最初如此緩慢,我們首先需要了解過去是如何做聲明式UI的。

Virtual DOM最初是由React的作者開創(chuàng)的,目的是使聲明式UI的渲染速度更快。為了理解為什么聲明式UI最初如此緩慢,我們首先需要了解過去是如何做聲明式UI的。

聲明式用戶界面

編寫聲明式UI的傳統(tǒng)方法是更改元素的innerHTML屬性。例如,如果我想向<div>UI添加一個元素到,我將寫如下:

document.body.innerHTML = '<div>Hello World!</div>';
// <body> now has a <div>Hello World!</div> child.

我們可以認識到innerHTML允許我們以聲明地方式定義UI,但它的效率不高。

效率低下源于每次更改用戶界面時的解析、破壞和重建innerHTML,都需要遵循四個步驟:

  1. 解析innerHTML字符串到DOM節(jié)點樹中。
  2. 移除所有內容<body>元素。
  3. 將DOM節(jié)點樹插入<body>元素。
  4. 執(zhí)行布局計算和重繪屏幕。

這個過程在計算上非常昂貴,并且可能導致渲染速度顯著降低。

命令式用戶界面

那么,這個問題是如何解決的呢?那就是選擇使用DOM, 這種方法要比innerHTML方法快3倍。

const div = document.createElement('div');
div.textContent = 'Hello World!';
document.body.appendChild(div);

然而,我們可以認識到,手動編寫這個可能很麻煩,特別是當UI中有很多交互時,因為我們需要命令式地指定每個步驟。以聲明的方式編寫UI要優(yōu)雅得多。

不過,React作者創(chuàng)建了VirtualDOM,允許我們以一種比innerHTML更快的呈現(xiàn)方式編寫UI,而且是聲明式的。

理解VirtualDOM

為了最好地了解VirtualDOM是如何工作的,讓我們概述一下流程,然后構建一個示例。

VirtualDOM是一種呈現(xiàn)UI的方法。該方法利用模仿DOM樹的JavaScript對象樹(“虛擬”節(jié)點)。

// <div>Hello World!</div>
const div = document.createElement('div');
div.style = 'color: red';
div.textContent = 'Hello World!';

以上<div> 被模仿為以下JavaScript對象中的虛擬節(jié)點:

const divVNode = {
type: 'div',
props: {
style: 'color: red'
}
children: ['Hello World!']
};

我們可以注意到虛擬節(jié)點有三個屬性:

  • tag:將元素的標記名稱存儲為字符串。
  • props:將元素的屬性和屬性存儲為對象。
  • children:將元素的虛擬節(jié)點子級存儲為數(shù)組。

使用虛擬節(jié)點,我們可以對當前的UI進行建模,以及當我們更新UI時希望它改變成什么。

假設我想將<div>中的文本從 "Hello World!" 更改成 "Hello Universe!"。可以使用DOM進行強制修改:

// <div>Hello World!</div>
const div = document.createElement('div');
div.style = 'color: red';
div.textContent = 'Hello World!';

// Change from "Hello World!" to "Hello Universe!"
div.textContent = 'Hello Universe!';

但是使用VirtualDOM,我可以指定當前UI的外觀(舊虛擬節(jié)點)和我希望它的外觀(新虛擬節(jié)點)。

const oldVNode = {
type: 'div',
props: {
style: 'color: red'
}
children: ['Hello World!']
};

const newVNode = {
type: 'div',
props: {
style: 'color: red'
}
children: ['Hello Universe!']
};

然而要讓Virtual DOM真正將更改應用到UI,還需要計算舊虛擬節(jié)點和新虛擬節(jié)點之間的差異。

{
type: 'div',
props: {
style: 'color: red'
}
- children: ['Hello World!']
+ children: ['Hello Universe!']
};

當我們知道了二者之間的差別,就可以通過Virtual DOM改變UI。

div.replaceChild(newChild, oldChild);

Virtual DOM只是進行了必要的修改,并不是替換了整個UI。

構建自己的Virtual DOM

在本文中,我們將模仿Million.js的 Virtual DOM API。我們的API將包含三個主要功能:m, createElement, and patch。

m (tag, props, children)

m 函數(shù)是創(chuàng)建虛擬節(jié)點的輔助函數(shù)。虛擬節(jié)點包含三個屬性:

  • tag:將虛擬節(jié)點的名稱標記為字符串;
  • props:作為對象的節(jié)點的屬性/屬性;
  • children:虛擬節(jié)點的子節(jié)點作為數(shù)組。

m幫助程序函數(shù)的示例實現(xiàn)如下:

const m = (tag, props = {}, children = []) => ({
tag,
props,
children,
});

這樣創(chuàng)建虛擬節(jié)點就簡單多了。

m('div', { style: 'color: red' }, ['Hello World!']);

#createElement(vnode)

該createElement函數(shù)將虛擬節(jié)點轉換為真實的DOM元素。這很重要,因為我們將在patch函數(shù)中使用它。

實現(xiàn)如下:

  1. 如果虛擬節(jié)點是文本,則返回文本節(jié)點;
  2. tag使用虛擬節(jié)點的屬性創(chuàng)建一個新的DOM節(jié)點;
  3. 遍歷虛擬節(jié)點props 并將它們添加到DOM節(jié)點。
  4. 遍歷children,在每個子級上遞歸調用createElement并將其添加到DOM節(jié)點。
const createElement = (vnode) => {
if (typeof vnode === 'string') {
return document.createTextNode(vnode);
}
const el = document.createElement(vnode.tag);
for (const prop in vnode.props) {
el[prop] = vnode.props[prop];
}
for (const child of vnode.children) {
el.appendChild(createElement(child));
}
return el;
};

這樣就可以輕松地將虛擬節(jié)點轉變成DOM節(jié)點。

// <div style="color: red">Hello World!</div>
createElement(
m('div', { style: 'color: red' }, ['Hello World!'])
);

#patch(el, newVNode, oldVNode)

該patch函數(shù)采用現(xiàn)有的DOM節(jié)點、舊的虛擬節(jié)點和新的虛擬節(jié)點。

實現(xiàn)如下:

  1. 計算兩個虛擬節(jié)點之間的差異;
  2. 如果虛擬節(jié)點是字符串,則將DOM節(jié)點的文本內容替換為新節(jié)點;
  3. 如果虛擬節(jié)點是對象,且tag、props、 children不同,則更新節(jié)點。
const patch = (el, newVNode, oldVNode) => {
if (!newVNode && newVNode !== '') return el.remove();
if (
typeof oldVNode === 'string' ||
typeof newVNode === 'string'
) {
if (oldVNode !== newVNode) {
return el.replaceWith(createElement(newVNode));
}
} else {
if (oldVNode.tag !== newVNode.tag) {
return el.replaceWith(createElement(newVNode));
}

// patch props
for (const prop in {
...oldVNode.props,
...newVNode.props,
}) {
if (newVNode.props[prop] === undefined) {
delete el[prop];
} else if (
oldVNode.props[prop] === undefined ||
oldVNode.props[prop] !== newVNode.props[prop]
) {
el[prop] = newVNode.props[prop];
}
}

// patch children
for (let i = oldVNode.children.length - 1; i >= 0; --i) {
patch(
el.childNodes[i],
newVNode.children[i],
oldVNode.children[i]
);
}

for (
let i = oldVNode.children.length;
i < newVNode.children.length;
i++
) {
el.appendChild(createElement(newVNode.children[i]));
}
}
};

這樣就可以使用patch功能更新UI了。

const oldVNode = m('div', { style: 'color: red' }, [
'Hello World!',
]);
const newVNode = m('div', { style: 'color: red' }, [
'Hello Universe!',
]);
const el = createElement(oldVNode);

// <div style="color: red">Hello World!</div>
patch(el, oldVNode, newVNode);
// <div style="color: red">Hello Universe!</div>

Virtual DOM是純開銷

當前,Virtual DOM實現(xiàn)在計算新舊虛擬節(jié)點之間的差異時會產生計算成本。

即使使用非常有效的差分算法 (如list-diff2),當虛擬節(jié)點樹大于虛擬節(jié)點的兩位數(shù)時,差異成本也會變得顯著。

樹區(qū)分算法是出了名的慢。時間復雜度可以從O(n)轉O(n ^ 3)取決于虛擬節(jié)點樹的復雜性。這與DOM操縱相去甚遠,后者是O(1)。

Virtual DOM的未來

編譯器是新框架”-- 湯姆·戴爾

Ember的創(chuàng)建者湯姆是最早倡導為JavaScript UI庫使用編譯器開源狂熱者之一。

現(xiàn)在,我們知道湯姆的賭注是正確的。JavaScript生態(tài)系統(tǒng)見證了Solid、Svelte等“已編譯”庫的興起,它們放棄了Virtual DOM。這些庫使用編譯器預渲染,并在使用時生成代碼來跳過不必要的渲染。

另一方面,Virtual DOM落后于這一趨勢。當前的虛擬DOM庫本質上與“按需” 編譯器不兼容。因此,Virtual DOM的渲染速度通常是比現(xiàn)代“No Virtual DOM” UI庫慢幾個數(shù)量級。

如果我們希望Virtual DOM在未來的渲染速度上具有競爭力,那就需要重新設計Virtual DOM以允許編譯器增強。

責任編輯:黃顯東 來源: 51CTO
相關推薦

2021-07-26 10:42:49

云計算AIOps人工智能

2021-05-26 05:22:09

Virtual DOMSnabbdom虛擬DOM

2023-03-21 11:24:44

eSIM移動通信

2020-10-12 08:56:47

Virtual dom

2021-06-21 07:36:32

Virtual DOMDOMvue.js

2009-07-14 08:45:58

Google操作系統(tǒng)版本歷史未來發(fā)展

2024-08-13 08:09:34

2014-12-08 11:01:09

openstack網絡network

2018-01-02 13:30:04

代碼質量代碼預言

2024-04-11 08:02:11

算法用戶畫像深度學習

2011-06-15 15:48:52

HTML 5

2021-07-04 10:07:04

Virtual DO閱讀源碼虛擬DOM

2010-09-28 11:11:23

XML DOMHTML DOM

2015-09-18 09:53:21

中間件移動開發(fā)APP

2015-11-28 10:05:49

數(shù)據變現(xiàn)

2009-07-17 09:07:20

2015-09-18 09:20:31

中間件移動APP未來

2010-09-28 11:22:18

Html DOM樹

2015-08-10 10:58:53

dompropertyattribute

2012-02-13 09:45:10

SUSE
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一区 中文字幕 | 色久伊人 | 久草视频观看 | 日韩高清成人 | 成人在线免费 | 特黄色一级毛片 | 9191成人精品久久 | 九九热精品在线视频 | 成人黄色在线 | 亚洲a视 | 日韩伦理电影免费在线观看 | 国产一区二区三区四区 | 精品久久久久香蕉网 | 日韩视频在线观看中文字幕 | 久久久久久国 | 99re在线 | 日韩精品专区在线影院重磅 | 精品一区二区在线观看 | 天天操夜夜操 | 国产高清免费 | 日韩最新网站 | 日本黄色影片在线观看 | 久草精品视频 | 黄色小视频入口 | 一级黄在线观看 | 久久久av| 麻豆精品国产91久久久久久 | 国产伦精品一区二区三区照片91 | 亚洲免费大片 | 欧美精品1区2区3区 精品国产欧美一区二区 | 中文字幕四虎 | 亚洲国产成人av好男人在线观看 | av久久| 亚洲日韩中文字幕一区 | 91精品国产91久久久久久密臀 | 成人在线电影网站 | 精品福利视频一区二区三区 | 99精品久久久 | 日韩精品不卡 | 日日操操 | 国产精品永久免费观看 |