React 核心

88 阅读2分钟

1.开发环境搭配

npm init npm i webpack webpack-cli --dev --save 创建webpack.config,js 配置文件 复制粘贴内容 创建src目录 index.js npm i react react-dom --dev --save npm i --save --dev @babel/core babel-loader @babel/preset-env @babel/preset-react npm i html-webpack-plugin

src目录下创建template文件夹-index.html 文件

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start:dev": "webpack-dev-server --open"
  }
npm i webpack-dev-server

import React from 'react'
import ReactDOM from 'react-dom'
ReactDOM.render(<div>HELLO</div>,document.querySelector('#app'))

三个核心概念

  • Component

  • Element

  • Instance

这三个核心概念是react运行的基石,我们想弄清楚react运行原理,必须先搞清楚它们的区别与联系。

Element

Element 是一个纯 JavaScript Object。React 正是使用它来描述整个 DOM 树的结构。对于每一个组件来说,render 函数返回的也正是一个 element,而不是真正的 DOM 节点。

{
  type: 'div',
  props: {
    className,
    children,
  }
}

babel在线测试babeljs.io/repl/

面试题: react中的render函数返回值是什么?

render 函数返回的也正是一个 element,而不是真正的 DOM 节点。通过react.createElement来的

Component

Component 是我们最常写的“组件”,有以下几种类型:

  • DOMComponent: div, span, ul

  • CompositeComponent: 复合组件,又分为 functional component 和 class component

  • TextComponent: number or string

EX:Clock就一个Component类

image.png

由于我们在使用 React 实现组件化的时候,使用的有且只有 CompositeComponent,所以,我们的每一个组件,其实都是一个 Component。但是当 React 试图去 render 这些组件的时候,会将 Element 转化成 Component,进而转化成真正的 DOM 节点

Instance

Instance 是 Component 的实例化之后的对象,我们在 Component 中使用的 this 就是 instance。这也是 setState 和诸多生命周期函数所在的地方。从这一点出发,可以把 Component 理解为 Class,instance是实例化后的结果。

image.png

createElement实现

如何思考

  1. element长什么样?

    type, props, children

  2. 接受几个参数

    无数个参数,从第三个开始都是子节点

function createElement(type, config, children) {
    const props = Object.assign({}, config);
    // 判断参数长度
    const childrenLenth = [].slice.call(arguments).length - 2;

    if (childrenLenth > 1) {
        props.children = [].slice.call(arguments, 2);
    } else if (childrenLenth === 1) {
        // 长度 = 1
        props.children = children;
    }

    return {
        type,
        props
    }
}

render实现

注意: 这里的render是ReactDom.render不是componnet中的rendera

function render(element, node) {

    // element 最终会转换成真实的节点
    // 转换过程
    // component componentDidMount  返回一个真实的节点 

    // element => component => componentDidMount

    // 将element生成一个组件类,然后实例化这个组件,调用didMount方法,得到一个真实节点
    // debugger;
    var component = instantiateComponent(element);
    var renderDom = component.mountComponent();

    // var dom = document.createElement('div')
    node.append(renderDom);
}

instantiateComponent实现

将element变为组件并且实例化。

element的三种类型:

  • function
  • string
  • 原生dom节点
function instantiateComponent(element) {
    var componentInstance;

    if (typeof element.type === 'function') {
        // element.type 本身就是一个复合组件
        componentInstance = new element.type(element.props);  // 得到复合组件的实例
    } else if (typeof element.type ==='string') {
        componentInstance = new DomComponent(element);
    } else if (typeof element === 'string' ||  typeof element === 'number') {
        componentInstance = new DomComponent({
            type: 'span',
            props: {children: element}
        });
    }

    return componentInstance;
}

DomComponent