React初始化渲染過程示例詳解
正文
初始化渲染的過程,我們可以直接對應(yīng)到React程序中ReactDOM.render函數(shù)調(diào)用后的結(jié)果。
1.環(huán)境準(zhǔn)備
初始化項目:
npx create-react-app simple-react
刪除一些代碼,最關(guān)鍵的內(nèi)容就是:
src/index.js
public/index.html
package.json中的dependencies和scripts:
2.JSX介紹
JSX是JavaScript的一種語法擴展。
JSX到普通Javascript的代碼的轉(zhuǎn)化是通過babel完成的。
3.React.createElement編寫
DISABLE_NEW_JSX_TRANSFORM=true 禁用掉新的jsxdev轉(zhuǎn)換,使用React.createElement
這個迷你的包(cross-env)能夠提供一個設(shè)置環(huán)境變量的scripts,讓你能夠以unix方式設(shè)置環(huán)境變量,然后在windows上也能兼容運行。
npm i cross-env -D
package.json
"start": "cross-env DISABLE_NEW_JSX_TRANSFORM=true react-scripts start",
react17之前通過Babel把jsx轉(zhuǎn)換為虛擬DOM
<div> Hello Simple React </div>
React.createElement("div", null, "Hello Simple React")
react.js
import { REACT_ELEMENT } from "./utils" function createElement(type, properties, children) { // debugger let ref = properties.ref || null let key = properties.key || null // 屬性可以是可讀的、可寫的或可刪除的。 // 屬性可以是可枚舉的(可以通過for…in循環(huán)枚舉)或不可枚舉的。 // 可以通過Object.defineProperty()等方法定義屬性的特性。 ;['key', 'ref', '__self', '__source'].forEach(key => { delete properties[key] }) let props = { ...properties } //傳參大于3 if (arguments.length > 3) { console.log(arguments) props.children = Array.prototype.slice.call(arguments, 2) } else { props.children = children } return { //$$--唯一性,jsx轉(zhuǎn)換成為的類型 $$typeof: REACT_ELEMENT, type, ref,//操作DOM key,//diff比較 props } } const React = { createElement } export default React
4.ReactDOM.render函數(shù)編寫
初始化渲染第一步:實現(xiàn)函數(shù)React.createElement
初始化渲染第二步:實現(xiàn)函數(shù)ReactDOM.render
react-dom.js
import { REACT_ELEMENT } from './utils' //初始化渲染(不止掛載操作) function render(VNode, containerDOM) { // 將虛擬DOM轉(zhuǎn)化成真實DOM // 將得到的真實DOM掛載到contanerDOM中 mount(VNode, containerDOM) } function mount(VNode, containerDOM) { let newDOM = createDOM(VNode) newDOM && containerDOM.appendChild(newDOM) } function createDOM(VNode) { // 1.根據(jù)類型創(chuàng)建元素 2.處理子元素,VNode是樹形結(jié)構(gòu) 3.處理屬性值 const { type, props } = VNode let dom; //typeof === REACT_ELEMENT代表虛擬DOM VNode if (type && VNode.$$typeof === REACT_ELEMENT) { dom = document.createElement(type) } if (props) { //子節(jié)點存在 if (typeof props.children === 'object' && props.children.type) { //遞歸,創(chuàng)建子節(jié)點 mount(props.children, dom) } else if (Array.isArray(props.children)) { //多個子節(jié)點 mountArray(props.children, dom) } else if (typeof props.children === 'string') { //文本節(jié)點 dom.appendChild(document.createTextNode(props.children)) } } // TODO:處理屬性值 //setPropsForDOM(dom, props) return dom } //多個子節(jié)點處理 function mountArray(children, parent) { console.log('parent', parent, children) if (!Array.isArray(children)) return for (let i = 0; i < children.length; i++) { if (typeof children[i] === 'string') { //創(chuàng)建文本節(jié)點 parent.appendChild(document.createTextNode(children[i])) } else { mount(children[i], parent) } } } const ReactDOM = { render } export default ReactDOM
5.實現(xiàn)函數(shù)setPropsForDOM進行屬性更新
// 【這里需要注意jsx屬性名稱的寫法】
ReactDOM.render(<div className='test-class' style={{color: 'red'}}>Simple React App<span>xx1</span><span>xx2</span></div>, document.getElementById('root'))
function setPropsForDOM(dom, VNodeProps = {}) { if (!dom) return for (let key in VNodeProps) { if (key === 'children') continue //^開頭,on開頭,A-Z之間一個,.匹配單個字符, //*號匹配一個字母或者數(shù)字出現(xiàn)一次或者多次 onclick if (/^on[A-Z].*/.test(key)) { // TODO: 事件處理 } else if (key === 'style') { Object.keys(VNodeProps[key]).forEach(styleName => { dom.style[styleName] = VNodeProps[key][styleName] }) } else { dom[key] = VNodeProps[key] } } }
總結(jié)
從JSX源代碼(<div>Hello JSX</div>)到顯示到界面上,需要經(jīng)歷哪些關(guān)鍵環(huán)節(jié)。
JSX -> 轉(zhuǎn)譯成函數(shù)調(diào)用 -> 執(zhí)行函數(shù)調(diào)用返回虛擬DOM -> 將虛擬DOM轉(zhuǎn)化成DOM -> 將生成的DOM掛載到DOM上
以上就是React初始化渲染過程示例詳解的詳細內(nèi)容,更多關(guān)于React初始化渲染的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
react-native組件中NavigatorIOS和ListView結(jié)合使用的方法
這篇文章主要給大家介紹了關(guān)于react-native組件中NavigatorIOS和ListView結(jié)合使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09react?+?vite?+?ts項目中優(yōu)雅使用.svg文件
這篇文章主要為大家介紹了react?+?vite?+?ts項目中優(yōu)雅使用.svg文件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08react navigation中點擊底部tab怎么傳遞參數(shù)
本文主要介紹了react navigation中點擊底部tab怎么傳遞參數(shù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04React + webpack 環(huán)境配置的方法步驟
本篇文章主要介紹了React + webpack 環(huán)境配置的方法步驟,詳解的介紹了開發(fā)環(huán)境的配置搭建,有興趣的可以了解一下2017-09-09