前言
当前公司的技术栈还是以React为主,看了很多 jd 都要求需要对源码有了解甚至需要会写简单的源码实现,说干就干
初始化react项目
- cnpm i create-react-app -g
- create-react-app myReact
- 删除所有无关文件 仅留入口文件
4.我的react版本是17.0.2
- 4.1 17以后的jsx编译不再生成React.createElement
- 4.2 是在babel编译阶段 会自动import {jsx} from “react/jsx-runtime” jsx()替代createElement ,目的可能是为了解耦 ,项目里可以不做import React from “react”;
- 4.3 script里将jsx() 禁用 因为要自己实现 createElement方法
- 4.4 npm run eject的坑,没事不要做弹出配置操作,原因是react17更改了jsx的转化规则 需要在script里set DISABLE_NEW_JSX_TRANSFORM=true ,来禁用jsx(),但弹出了配置后会一直禁用不成功 打包会报错(也留了一个坑,我没有找到为什么弹出后会一直禁用不成功)
React.createElement实现
-
createElement作用
生成vdom用于做render参数
-
确定createElement入参
- createElement出参
- type:标签类型
- props:标签属性和children元素
- createElement 过程
* @param type 元素类型
* @param config 元素的配置对象
* @param children 元素的子元素们
*/
function createElement(type, config, children) {
// 解构config
let props = { ...config };
//判断方法入参 长度,
// 大于3 则存在子元素(有标签的子元素)
if (arguments.length > 3) {
//获取子元素
children = Array.prototype.slice.call(arguments, 2);
}
props.children = children;
return {
type,
props,
};
}
const React = { createElement };
export default React;
复制代码
React.render的实现
- 思路
- vdom变真实dom
- 虚拟dom属性同步给真实dom
- 递归childrenDom
- append到目标容器
- 实现过程
- render方法要做的事:vdom转化真实DOM
/**
* @param vdom 要渲染的虚拟对象
* @param container append的目标容器节点
*/
function render(vdom, container) {
//vdom转化真实DOM
const dom = function(vdom){
//vdom的类型:字符串,数字,直接返回文本节点
if(typeof vdom === "string" || typeof vdom === "number"){
document.createTextNode(vdom)
}
//否则就是一个虚拟对象---即:react元素 返回对应标签
let { type, props } = vdom;
let dom = document.createElement(type);
//为dom设置样式 style,className
//判断props.children 类型
if (
typeof props.children === "string" ||
typeof props.children === "number"
){
//children 只是文档
dom.textContent = props.children;
}else if (typeof props.children === "object" && props.children.type) {
//children也是一个vdom
//递归render,目标容器变成自己做后面的append
render(props.children, dom);
} else if (Array.isArray(props.children)) {
//多个子元素的处理
//for循环 依次调用render();
}
return dom;
};
container.appendChild(dom);
}
复制代码
调用render,reateElement
import ReactDOM from "./react-dom";
ReactDOM.render(
React.createElement(
"div",
{
className: "title",
style: {
color: "red",
},
},
React.createElement("span", null, "hello"),
"world"
),
document.getElementById("root")
);
复制代码
效果
最后如果觉得本文有帮助 记得点赞三连哦 十分感谢
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END