Implement React Hooks
DAY 1
为了加深对React的理解,从今天开始,打算花一周时间,手动实现一些常用的Hooks,从最基础的React.createElement()和ReactDOM.render()开始
React.createElement(type,props,...childern)
功能
- 格式化,将参数“打包”成统一格式的对象并返回,方便下一步交给
ReactDOM.render()处理
参数
type,接受字符串,字符串对应要创建的 DOM 元素props,接受对象,对象的属性值将附加到 DOM 元素上...childern,接受多个参数,参数类型可以是字符串(文本节点)或者对象(DOM 节点),作为所创建元素的子节点
code
const createElement = (type, props, ...children) => {
return {
type,
props: {
...props,
children: children?.map(child =>
typeof child === "object"
? child
: createTextElement(child)
)
}
}
}
const createTextElement = (text) => {
return {
type: 'TEXT_ELEMENT',
props: {
nodeValue: text,
children: []
}
}
}
export default createElement
points
- 拓展运算符:函数支持传入多个参数、对象解构
- 命名空间:
type: 'TEXT_ELEMENT',唯一标识,Redux中有类似结构,常用于判断/分支语句
React.render(element,container)
功能(React 18 已经不支持)
- 解析参数,创建节点树并挂载到父(根)节点上,触发浏览器渲染
参数
element,React.createElement()返回的格式化对象,根据此对象生成节点树container,DOM 节点(React App 一般只有一个根节点),用于挂载element对应的节点树
code
const render = (element, container) => {
const dom =
element.type === 'TEXT_ELEMENT'
? document.createTextNode("")
: document.createElement(element.type)
const isProperty = key => key !== 'children'
Object.keys(element?.props)
.filter(isProperty)
.forEach(name => dom[name] = element.props[name])
element?.props?.children?.forEach(child => render(child, dom))
container.appendChild(dom)
}
export default render
points
.filter():数组方法,用于过滤出符合条件的数组元素- 遍历对象:
Object.keys()返回由对象属性名组成的数组 - 递归:若还有子元素,则继续调用
render(child,dom),将其挂载到上一节点,最终生成节点树