本文主要介紹React 大概思路兼蜈,實現自己的簡易版React固灵。知其然知其所以然,用了React必定要了解和掌握其中的知識锣光。廢話不多說....
- React之JSX和虛擬DOM (當前)
- React之組件實現
- React之生命周期方法
- React之Diff算法
- React之封裝子組件更新
- React之異步的setState
1.用過React的同學都知道踪危,在我們開發(fā)過程中都會引用React和ReactDOM蔬浙,同時我們也必須知道
React.createElement()
和ReactDOM.render()
這兩個方法,我們就從這里開始講起贞远。
2.我們同時也要裝幾個babel的插件npm i babel-core babel-preset-env babel-plugin-transform-react-jsx
將jsx語法轉換成js對象(虛擬dom)
3.這里打包用的是 parcelnpm install -g parcel-bundler
可以去官網了解parcel
.babelrc 配置文件
{
"presets": ["env"],
"plugins": [
["transform-react-jsx", {
"prama": "React.createElement"
}]
]
}
1.index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src='index.js'></script>
</body>
</html>
2.index.js文件
import React from './react';
import ReactDOM from './react-dom';
const ele = (
<div className="ele" title="123">
hello,<span>react</span>
</div>
)
ReactDOM.render(ele, document.querySelector('#root'))
3.react
const React = {
createElement
}
function createElement(tag, attrs, ...childrens) {
return {
tag, //外層標簽
attrs, //屬性 是一個對象
childrens //子級節(jié)點 是一個數組
}
};
export default React
- react 目前只有一個文件 index.js
createElement(tag,attrs,child1,child1...)
會將我們的組件轉換成對象形式
4.react-dom
render(vnode, container)
方法
1.vnode
是我們的虛擬dom畴博,就是createElement
所返回的對象
2.container
就是我們前邊用到的document.querySelector('#root')
setAttribute(dom, key, val)
方法
1.dom
當前節(jié)點
2.key
比如className、styel蓝仲、onClick
3.val
屬性值- 代碼里面的每一步注釋都寫的很清楚俱病,剩下的大家可以看代碼了
const ReactDOM = {
render
}
// 渲染
function render(vnode, container) {
// 如果不存在
if (!vnode) return
//如果是字符串
if (typeof vnode === 'string') {
const str = document.createTextNode(vnode)
return container.appendChild(str)
}
//如果是個對象
if (typeof vnode === 'object') {
// 標簽 屬性 子級
const { tag, attrs, children } = vnode
if (tag) {
// 創(chuàng)建節(jié)點對象
const dom = document.createElement(tag)
// 屬性 val :attrs[key]
if (attrs) {
Object.keys(attrs).forEach(key => {
const val = attrs[key]
setAttribute(dom, key, val)
})
}
// 遞歸調用 child == vnode, dom == container
vnode.childrens.forEach(child => render(child, dom))
return container.appendChild(dom)
}
}
}
// 設置屬性
function setAttribute(dom, key, val) {
//將classNname轉換class
if (key == 'className') key = 'class'
//事件 onClick :onclick 正則
if (/on\w+/.test(key)) {
key = key.toLowerCase()
dom[key] = val
} else if (key == 'style') {
// 如果沒有或者是字符串
if (!val || typeof val == 'string') {
dom.style.cssText = val
} else if (typeof val == 'object') {
// 例如 { width:20 }
for (let k in val) {
// 數字
if (typeof val[k] == 'number') {
dom.style[k] = val[k] + 'px'
} else {
dom.style[k] = val[k]
}
}
}
} else {
// 其他屬性
if (key in dom) {
dom[key] = val || ''
}
if (val) {
dom.setAttribute(key, val)
} else {
dom.removeAttribute(key)
}
}
}
export default ReactDOM
5.兩個問題
1.為什么
ReactDOM.render()
必須要引入React?
2.函數組件袱结、類組件亮隙、創(chuàng)建出的對象是否又跟當前的ele
對象相似呢?
下篇文章《React之組件實現》我們就來實現對應的組件一些相關的封裝
5.小結
這些就是本篇文章的主要內容垢夹,有問題可以在下方提問溢吻,雙擊加關注,還可以打賞 哈哈哈 ??棚饵,謝謝大家煤裙!