摘要:我們用原生的對象來描述我們要渲染的東西,并稱這類對象為。下一步是將元素及其子元素渲染成。所以,將會使用來表示文本節(jié)點,并使用來裝文本值。創(chuàng)建添加事件監(jiān)聽設置屬性遞歸渲染子元素將添加到父內(nèi)我們目前創(chuàng)建了一個可以渲染元素及其子元素為的方法。
翻譯自這里:https://engineering.hexacta.c...
本系列的目的是創(chuàng)建類似于React的一個簡易的工具庫。
開始之前,我們先看下我們要用到的DOM API:
// 通過id查找元素 const domRoot = document.getElementById("root"); // 根據(jù)執(zhí)行標簽名創(chuàng)建元素 const domInput = document.createElement("input"); // 設置元素屬性 domInput["type"] = "text"; domInput["value"] = "Hi world"; domInput["className"] = "my-class"; // 添加事件監(jiān)聽 domInput.addEventListener("change", e => alert(e.target.value)); // 創(chuàng)建文本節(jié)點 const domText = document.createTextNode(""); // 設置節(jié)點內(nèi)容 domText["nodeValue"] = "Foo"; // 往頁面上添加元素 domRoot.appendChild(domInput); // 往頁面上添加文本節(jié)點 domRoot.appendChild(domText);
注意到這里我們給元素設置了properties而不是attributes,而且只有有效的properties才能被設置。
Didact Elements我們用原生的JS對象來描述我們要渲染的東西,并稱這類對象為Didact Elements。這些元素對應的JS對象都有兩個必要的屬性:type和props。type可以是個字符串也可以是一個函數(shù),但在我們介紹組件之前我們先只使用字符串。props是一個可以為空(null)的對象。props下還可以含有children屬性,children屬性值為一個裝有Didact Elements的數(shù)組。
我們后面將會頻繁的使用Didact Elements,所以我們會用元素稱呼Didact Elements。不要和HTML的元素搞混了,HTML元素會被稱作DOM元素或者使用命名變量時干脆就叫dom。
舉個例子,我們會用下面這個對象:
const element = { type: "div", props: { id: "container", children: [ { type: "input", props: { value: "foo", type: "text" } }, { type: "a", props: { href: "/bar" } }, { type: "span", props: {} } ] } };
來描述下面這個dom:
Didact Elements和React Elements很像。但通常情況下你不會使用JS手動去創(chuàng)建一個React Elements,更多的是使用JSX或者是createElement方法來創(chuàng)建。在Didact中我們也會使用相同的方法創(chuàng)建元素,但會將這部分內(nèi)容放在下一節(jié)。
Render DOM Elements下一步是將元素及其子元素渲染成dom。我們使用render(類似于ReactDOM.render)方法來接收一個元素和一個dom容器。這個方法會將這個元素描述的dom結構創(chuàng)建出來,并添加到容器內(nèi)。
function render(element, parentDom){ const { type, props } = element; const dom = document.createElement(type); const childElements = props.children || []; childElements.forEach(childElement => render(childElement, dom)); parentDom.appendChild(dom); }
我們現(xiàn)在仍沒有處理屬性和事件。我們先用Object.keys來獲取props中的屬性名字,然后循環(huán)將它們設定到元素上:
function render(element, parentDom){ const { type, props } = element; const dom = document.createElement(type); const isListener = name => name.startsWith("on"); Object.keys(props).filter(isListener).forEach(name => { const eventType = name.toLowerCase().substring(2); dom.addEventListener(eventType, props[name]); }) const isAttribute = name => !isListener(name) && name != "children"; Object.keys(props).filter(isAttribute).forEach(name => { dom[name] = props[name]; }) const childElements = props.children || []; childElements.forEach(childElement => render(childElement, dom)); parentDom.appendChild(dom); }Render DOM Text Nodes
目前render還不支持文本節(jié)點。首先我們要定義文本節(jié)點是什么樣的。在react中,一個Foo這樣的元素需要這樣描述:
const reactElement = { type: "span", props: { children: ["Foo"] } }
注意到這里的子元素已經(jīng)不是對象,而只是一個字符串。這和我們對Didact Elements的定義有不一樣:children應該是裝有Didact Elements的數(shù)組,并且所有元素都有type和props屬性。如果我們繼續(xù)遵守這個規(guī)則接下來我們將較少使用if的次數(shù)。所以,Didact Elements將會使用type="TEXT_ELEMENT"來表示文本節(jié)點,并使用nodeValue來裝文本值。例如下面這樣:
const textElement = { type: "span", props: { children: [ { type: "TEXT_ELEMENT", props: { nodeValue: "Foo" } } ] } };
現(xiàn)在我們已經(jīng)定義好了能夠渲染的文本節(jié)點。和其他節(jié)點不同的是,文本節(jié)點需要使用createTextNode來創(chuàng)建而不是createElement,而nodeValue會通過相同方法來設置。
function render(element, parentDom) { const { type, props } = element; // 創(chuàng)建DOM const isTextElement = type === "TEXT_ELEMENT"; const dom = isTextElement ? document.createTextNode("") : document.createElement(type); // 添加事件監(jiān)聽 const isListener = name => name.startsWith("on"); Object.keys(props).filter(isListener).forEach(name => { const eventType = name.toLowerCase().substring(2); dom.addEventListener(eventType, props[name]); }); // 設置屬性 const isAttribute = name => !isListener(name) && name != "children"; Object.keys(props).filter(isAttribute).forEach(name => { dom[name] = props[name]; }); // 遞歸渲染子元素 const childElements = props.children || []; childElements.forEach(childElement => render(childElement, dom)); // 將dom添加到父dom內(nèi) parentDom.appendChild(dom); }Summary
我們目前創(chuàng)建了一個可以渲染元素及其子元素為DOM的render方法。下一步我們需要一個快速簡單的方法來創(chuàng)建元素。下一節(jié)我們將在Didact中使用JSX。
下一節(jié):
https://engineering.hexacta.c...
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/99669.html
摘要:渲染元素開場白接著上一節(jié)的講解后我們大概清楚了以下幾個事兒知道是個什么東東為什么要推薦使用以及的一些基本語法。本篇文章談一下是怎么渲染元素的。更新已渲染的元素元素是不可變的,一旦你創(chuàng)建了一個元素,就不能再修改其子元素或任何屬性。 React-渲染元素 開場白 接著上一節(jié)JSX的講解后:我們大概清楚了以下幾個事兒: 知道JSX是個什么東東 為什么React要推薦使用JSX 以及JSX...
摘要:傳統(tǒng)算法通過循環(huán)遞歸對節(jié)點進行依次對比,效率低下,算法復雜度達到,其中是樹中節(jié)點的總數(shù)。對于同一層級的一組子節(jié)點,它們可以通過唯一進行區(qū)分。當發(fā)現(xiàn)節(jié)點已經(jīng)不存在,則該節(jié)點及其子節(jié)點會被完全刪除掉,不會用于進一步的比較。 https://zhuanlan.zhihu.com/p/... React diff 會幫助我們計算出 Virtual DOM 中真正變化的部分,并只針對該部分進行實...
摘要:事件行為在瀏覽器中保持一次,并且符合標準。主要是進行修復。事件已經(jīng)在移動上支持。阻止已經(jīng)在上存在的事件錯誤處理。然后對應的將會被打包送往客戶端。在中棄用,現(xiàn)在正式刪除。是運行于一個嚴格的安全策略下成為可能。增加警告提示非生產(chǎn)環(huán)境。 ??寫在開頭 閱讀React官網(wǎng)的 RECENT POSTS的個人翻譯/摘要(部分)。 英文片段為官網(wǎng)原文片段。 原文地址 ??為什么要使用React ...
摘要:注不做翻譯是中最小的構建部件。在里渲染讓我們看一下在下面有在你文件中無處不在的標簽我們會把這元素成為元素因為的所有東西都會放在這個元素里面。通過方法,我們能吧渲染到我們根節(jié)點上。更新被渲染的是不可變的。 下面是react官方文檔的個人翻譯,如有翻譯錯誤,請多多指出原文地址:https://facebook.github.io/re...特別感謝Hevaen,同時也向豪大React群所有...
閱讀 2906·2021-11-15 11:39
閱讀 1527·2021-08-19 10:56
閱讀 1100·2019-08-30 14:12
閱讀 3748·2019-08-29 17:29
閱讀 725·2019-08-29 16:21
閱讀 3427·2019-08-26 12:22
閱讀 1522·2019-08-23 16:30
閱讀 1029·2019-08-23 15:25