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类
由于我们在使用 React 实现组件化的时候,使用的有且只有 CompositeComponent,所以,我们的每一个组件,其实都是一个 Component。但是当 React 试图去 render 这些组件的时候,会将 Element 转化成 Component,进而转化成真正的 DOM 节点。
Instance
Instance 是 Component 的实例化之后的对象,我们在 Component 中使用的 this 就是 instance。这也是 setState 和诸多生命周期函数所在的地方。从这一点出发,可以把 Component 理解为 Class,instance是实例化后的结果。
createElement实现
如何思考
-
element长什么样?
type, props, children
-
接受几个参数
无数个参数,从第三个开始都是子节点
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;
}