react 学习(二) 实现类和函数式组件

我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调用函数返回虚拟 dom,一个是调用实例的 render 方法,返回虚拟 dom,进而转换为真实 dom,本小节我们了解一下具体的实现原理。

函数式组件

特点

  1. 函数组件接受一个单一的 props 对象并返回一个 react 元素
  2. 组件以大写字母开头(内部判断是原生还是自定义)
  3. 组件必须在使用时定义或引用
  4. 组件返回值只能有一个根元素(便于树遍历)
  5. React 元素不但可以使dom标签,也可以是用户自定义的组件
  6. react 元素为用户自定义组件时,他会将 jsx 接收的属性转换为单个对象换递给组件,即 props(babel 处理的)

使用

// index.js
function FunctionComponent(props) {
  let jsx = (
    <h1 className="title" style={{ color: "red", backgroundColor: "pink" }}>
      hello
      <span>111</span>
    </h1>
  );
  return jsx;
}
const el = <FunctionComponent msg='world' />;
console.log(el);
ReactDOM.render(el, document.getElementById("root"));

我们可以看到,函数组件返回的虚拟 dom 类型是函数类型,我们要修改我们的 createDOM 方法,实现函数式

实现

修改 createDOM 方法

// react-dom.js
...
if (typeof type === 'function') { // 上面截图我们看到函数组件的类型是个函数
  return mountFunctionComponent(vdom)
}
...


function mountFunctionComponent(vdom) {
  // 这里是 babel 编译时把我们写的属性转为了 props 对象形式
  const {type, props} = vdom
  const renderVdom = type(props)
  return createDOM(renderVdom)
}

入口文件改为自己的文件,打印如下:

类组件

react hooks 出现之前,想实现组件内容变化做不到,定义状态并改变状态只能使用类组件的方式。

使用

// index.js
class ClassComponent extends React.Component {
  render() {
    // 返回react 元素
    let jsx = (
      <h1 className="title" style={{ color: "red", backgroundColor: "pink" }}>
        hello
        <span>{this.props.msg}</span>
      </h1>
    );
    return jsx;
  }
}
const el = <ClassComponent msg="world" />;
console.log(el);
ReactDOM.render(el, document.getElementById("root"));

通过打印我们可以看到,类组件的类型是一个类。而且需要继承 React 对象的 Component 属性

实现

我们知道 javascript 本身是没有类的,es6 的类转化之后也会变成函数,这就会跟函数式组件的类型判断冲突,所以我们需要给类加上标识符

// react.js
// 我们逆推
const React = {
  createElement,
  Component
}

因为可以被继承,所以 Component 也是一个类

// src/Component.js
export class Component {
  static isReactComponent = REACT_COMPONENT; // 区分标识
  constructor(props) {
    this.props = props;
  }
}


// constants.js
export const REACT_COMPONENT = Symbol("react.component"); // Symbol 独一无二的  无法覆盖 无法伪造

我们改造一下 createDOM 方法

if (typeof type === "function") {
  // 类也是个函数
  if (type.isReactComponent === REACT_COMPONENT) {
    return mountClassComponent(vdom);
  }
  // 函数组件
  return mountFunctionComponent(vdom);
}


// 实现  mountClassComponent
function mountClassComponent(vdom) {
  const {type, props} = vdom
  const classInstance = new type(props) // 从打印中我们知道 type 是个类,可以被实例化
  const renderVdom = classInstance.render()
  return createDOM(renderVdom) // 虚拟dom转为真实dom
}

我们可以看到,无论是函数式组件还是类组件,本质都是返回处理的虚拟 dom,也就是基于上一小节的知识。这两个实现还不算复杂,跟着小编简单写写就可以掌握。下一小节我们学习下组件的更新机制,如果有不对,欢迎指正!

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
react 学习(二) 实现类和函数式组件
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
<<上一篇
下一篇>>