React初始化渲染過(guò)程示例詳解
正文
初始化渲染的過(guò)程,我們可以直接對(duì)應(yīng)到React程序中ReactDOM.render函數(shù)調(diào)用后的結(jié)果。
1.環(huán)境準(zhǔn)備
初始化項(xiàng)目:
npx create-react-app simple-react
刪除一些代碼,最關(guān)鍵的內(nèi)容就是:
src/index.js
public/index.html
package.json中的dependencies和scripts:
2.JSX介紹
JSX是JavaScript的一種語(yǔ)法擴(kuò)展。
JSX到普通Javascript的代碼的轉(zhuǎn)化是通過(guò)babel完成的。
3.React.createElement編寫(xiě)
DISABLE_NEW_JSX_TRANSFORM=true 禁用掉新的jsxdev轉(zhuǎn)換,使用React.createElement
這個(gè)迷你的包(cross-env)能夠提供一個(gè)設(shè)置環(huán)境變量的scripts,讓你能夠以u(píng)nix方式設(shè)置環(huán)境變量,然后在windows上也能兼容運(yùn)行。
npm i cross-env -D
package.json
"start": "cross-env DISABLE_NEW_JSX_TRANSFORM=true react-scripts start",
react17之前通過(guò)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
// 屬性可以是可讀的、可寫(xiě)的或可刪除的。
// 屬性可以是可枚舉的(可以通過(guò)for…in循環(huán)枚舉)或不可枚舉的。
// 可以通過(guò)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 React4.ReactDOM.render函數(shù)編寫(xiě)
初始化渲染第一步:實(shí)現(xiàn)函數(shù)React.createElement
初始化渲染第二步:實(shí)現(xiàn)函數(shù)ReactDOM.render
react-dom.js
import { REACT_ELEMENT } from './utils'
//初始化渲染(不止掛載操作)
function render(VNode, containerDOM) {
// 將虛擬DOM轉(zhuǎn)化成真實(shí)DOM
// 將得到的真實(shí)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是樹(shù)形結(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é)點(diǎn)存在
if (typeof props.children === 'object' && props.children.type) {
//遞歸,創(chuàng)建子節(jié)點(diǎn)
mount(props.children, dom)
} else if (Array.isArray(props.children)) {
//多個(gè)子節(jié)點(diǎn)
mountArray(props.children, dom)
} else if (typeof props.children === 'string') {
//文本節(jié)點(diǎn)
dom.appendChild(document.createTextNode(props.children))
}
}
// TODO:處理屬性值
//setPropsForDOM(dom, props)
return dom
}
//多個(gè)子節(jié)點(diǎn)處理
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é)點(diǎn)
parent.appendChild(document.createTextNode(children[i]))
} else {
mount(children[i], parent)
}
}
}
const ReactDOM = {
render
}
export default ReactDOM5.實(shí)現(xiàn)函數(shù)setPropsForDOM進(jìn)行屬性更新
// 【這里需要注意jsx屬性名稱的寫(xiě)法】
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
//^開(kāi)頭,on開(kāi)頭,A-Z之間一個(gè),.匹配單個(gè)字符,
//*號(hào)匹配一個(gè)字母或者數(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初始化渲染過(guò)程示例詳解的詳細(xì)內(nèi)容,更多關(guān)于React初始化渲染的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
react-native-video實(shí)現(xiàn)視頻全屏播放的方法
這篇文章主要介紹了react-native-video實(shí)現(xiàn)視頻全屏播放的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
基于React和antd實(shí)現(xiàn)自定義進(jìn)度條的示例代碼
在現(xiàn)代 Web 開(kāi)發(fā)中,進(jìn)度條是一種常見(jiàn)且實(shí)用的 UI 組件,用于直觀地向用戶展示任務(wù)的完成進(jìn)度,本文將詳細(xì)介紹如何使用 React 來(lái)構(gòu)建一個(gè)自定義的進(jìn)度條,它不僅能夠動(dòng)態(tài)展示進(jìn)度,還具備額外的信息提示功能,需要的朋友可以參考下2025-03-03
從零開(kāi)始搭建一個(gè)react項(xiàng)目開(kāi)發(fā)
這篇文章主要介紹了從零開(kāi)始搭建一個(gè)react項(xiàng)目開(kāi)發(fā),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
React實(shí)現(xiàn)路由返回?cái)r截的三種方式
最近項(xiàng)目為了避免用戶誤操作導(dǎo)致數(shù)據(jù)丟失,增加返回?cái)r截功能,但是之前由于qiankun的報(bào)錯(cuò)導(dǎo)致這個(gè)功能一直有一些問(wèn)題,所以專門獨(dú)立搞了一個(gè)專題研究在react中各種方式實(shí)現(xiàn)這個(gè)功能,需要的朋友可以參考下2024-05-05
使用webpack配置react-hot-loader熱加載局部更新
這篇文章主要介紹了使用webpack配置react-hot-loader熱加載局部更新,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
react高階組件經(jīng)典應(yīng)用之權(quán)限控制詳解
在React中,高階組件是重用組件邏輯的一項(xiàng)高級(jí)技術(shù)。下面這篇文章主要給大家介紹了關(guān)于react高階組件經(jīng)典應(yīng)用之權(quán)限控制的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09
解決React報(bào)錯(cuò)Property 'X' does not 
這篇文章主要為大家介紹了解決React報(bào)錯(cuò)Property 'X' does not exist on type 'HTMLElement',有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12

