学习记录——简单地实现React Hooks

121 阅读1分钟

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 已经不支持)

  • 解析参数,创建节点树并挂载到父(根)节点上,触发浏览器渲染

参数

  • elementReact.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),将其挂载到上一节点,最终生成节点树