一、jsx变createElement

每一个用jsx语法书写的react组件最后都会变成 react.createElement(...)这一坨东西,

// 转变前

export default (props)=>(
<h1 ref="h1" key="header1" name="我"><span>哈哈!</span>我是header.{props.kk}</h1>
);
// 转变后
var _default = function _default(props) {
return _react2.default.createElement(
"h1",
{ ref: "h1", key: "header1", name: "\u6211" },
_react2.default.createElement(
"span",
null,
"\u54C8\u54C8\uFF01"
),
"\u6211\u662Fheader.",
props.kk
);
};

通过看代码就知道:header这个组件有三个子元素: span  text  变量

可以说每遇到一个html标签就用createElement做包装,text 和 变量 不包装,直接按顺序当做参数传入createElement,有多少传多少

二、createElement拿到这些参数都干了啥

撸到createElement的源码块所在文件:

// react中createElement方法来源于 ReactElement.js
import {
createElement,
createFactory,
cloneElement,
isValidElement,
} from './ReactElement';

找到createElement的源码:

/**
* 传入了如下参数:
* type: "h1"
* config: { ref: "h1", key: "header1", name: "\u6211" }
* children: 1.react.createElement(...)
* 2.'我是header'
* 3. props.kk
*/ function createElement(type, config, children) {
// 一堆变量初始化
let propName;
const props = {}; let key = null;
let ref = null;
let self = null;
let source = null;
// 如果组件上存在属性设置,比如ref、key 其他props什么的
if (config != null) {
// 判断是否有ref属性且ref属性有值 单独取出来
if (hasValidRef(config)) {
ref = config.ref;
}
// 判断是否有key,单独取出来
if (hasValidKey(config)) {
key = '' + config.key;
}
// 先不管self 跟 source是干什么用的
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source;
// 把剩余的属性塞到props里面
for (propName in config) {
if ( /*
const hasOwnProperty = Object.prototype.hasOwnProperty;
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true,
}; */
// 严谨的判断config对象中是否存在改属性,且属性名不能是react保留的那四种
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
// 放入props中
props[propName] = config[propName];
}
}
} // 处理后面那些children
// 算出有几个children
const childrenLength = arguments.length - 2; if (childrenLength === 1) {
// 如果就一个 直接赋值
props.children = children;
} else if (childrenLength > 1) {
// 整一个childArray 保存那些children
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
// dev环境不管丫的
if (__DEV__) {
....
}
// 最终还是塞到props里面
props.children = childArray;
} // 如果type传的东西是个对象,且type有defaultProps这个东西,那就defaultProps的值也塞props里面
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
if (__DEV__) {
... //附加一堆开发环境才有的东西,先不去管它
}
// 最后返回ReactElement 函数执行后的返回值
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props,
);
}

我们注意到里面有一个 ReactCurrentOwner.current这个东西是个外来的,找到它:

const ReactCurrentOwner = {
/**
* @internal
* @type {ReactComponent}
*/
current: (null: null | Fiber),
currentDispatcher: (null: null | Dispatcher),
}; // 实际上这个current初始时是null,类型可以是Fiber或null

其实绕来绕去,核心是 return ReactElement(...)这么一堆东西,就像剥洋葱,还得往下扒皮

三、ReactElement返回组件的真正形态

// 判断浏览器是否支持Symbol
const hasSymbol = typeof Symbol === 'function' && Symbol.for;
// 如果支持Symbol 则创建,否则用数字代替
export const REACT_ELEMENT_TYPE = hasSymbol
? Symbol.for('react.element')
: 0xeac7; const ReactElement = function(type, key, ref, self, source, owner, props) {
const element = {
$$typeof: REACT_ELEMENT_TYPE, // Symbol('react.element');
type: type, // h1
key: key, // header1
ref: ref, // h1
props: props, // {name:'\u6211',children:[...,...,...]}
_owner: owner, // null
}; if (__DEV__) {
...
} return element;
};

这个element打印出来,其实它就是一个简简单单的对象

其他:

Symbol.for('abc') 和  Symbol('abc')有什么区别呢?

React 16 源码瞎几把解读 【一】 从jsx到一个react 虚拟dom对象的更多相关文章

  1. React 16 源码瞎几把解读 【三 点 二】 react中的fiberRoot

    〇.先来看看常用的常量 NoWork = 0 noTimeout = undefined HostRoot = 3 NoContext = 0b000; AsyncMode = 0b001; Stri ...

  2. React 16 源码瞎几把解读 【二】 react组件的解析过程

    一.一个真正的react组件编译后长啥样? 我们瞎几把解读了react 虚拟dom对象是怎么生成的,生成了一个什么样的解构.一个react组件不光由若干个这些嵌套的虚拟dom对象组成,还包括各种生命周 ...

  3. React 16 源码瞎几把解读 【三 点 一】 把react组件对象弄到dom中去(矛头指向fiber,fiber不解读这个过程也不知道)

    一.ReactDOM.render 都干啥了 我们在写react的时候,最后一步肯定是 ReactDOM.render( <div> <Home name="home&qu ...

  4. React 16 源码瞎几把解读 【前戏】 为啥组件外面非得包个标签?

    〇.看前准备 1.自行clone react最新代码 2.自行搭建一个能跑react的test项目 一.看表面:那些插件 如何解析JSX 有如下一段代码: // ---- hearder.jsx 组件 ...

  5. 精读《React PowerPlug 源码》

    1. 引言 React PowerPlug 是利用 render props 进行更好状态管理的工具库. React 项目中,一般一个文件就是一个类,状态最细粒度就是文件的粒度.然而文件粒度并非状态管 ...

  6. React Fiber源码分析 (介绍)

    写了分析源码的文章后, 总觉得缺少了什么, 在这里补一个整体的总结,输出个人的理解~ 文章的系列标题为Fiber源码分析, 那么什么是Fiber,官方给出的解释是: React Fiber是对核心算法 ...

  7. 《React Native 精解与实战》书籍连载「React Native 源码学习方法及其他资源」

    此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React Native 源码学习方法及其他资源. 最后的章节给大家介绍 React Native ...

  8. React的React.createContext()源码解析(四)

    一.产生context原因 从父组件直接传值到孙子组件,而不必一层一层的通过props进行传值,相比较以前的那种传值更加的方便.简介. 二.context的两种实现方式 1.老版本(React16.x ...

  9. React的React.createElement源码解析(一)

    一.什么是jsx  jsx是语法糖  它是js和html的组合使用  二.为什么用jsx语法 高效定义模版,编译后使用 不会带来性能问题 三.jsx语法转化为js语法  jsx语法通过babel转化为 ...

随机推荐

  1. 第162天:canvas中Konva库的使用方法

    本篇接着上一篇:第157天:canvas基础知识详解  继续来写. 五.Konva的使用快速上手 5.1 Konva的整体理念 Stage | +------+------+ |            ...

  2. Spark:一个高效的分布式计算系统--转

    原文地址:http://soft.chinabyte.com/database/431/12914931.shtml 概述 什么是Spark ◆ Spark是UC Berkeley AMP lab所开 ...

  3. [二十]SpringBoot 之 (多)文件上传

    (1)新建maven Java project 新建一个名称为spring-boot-fileuploadmaven java项目 (2)在pom.xml加入相应依赖: <project xml ...

  4. 深入理解JVM一垃圾回收器

    上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃 ...

  5. 【JavaScript】面向对象的程序设计

    一.前言        接着上一篇的内容,继续JavaScript的学习. 二.内容 属性类型 //数据属性[Configurable] —— 能否通过delete删除属性从而重新定义属性,能否修改属 ...

  6. 洛谷 P2258 子矩阵

    题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...

  7. Linux之Makefile20160707

    说一下LINUX下的Makefile,直接根据实际碰到的Makefile进行解读: 当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile:M=$(PWD ...

  8. webstorm 激活破解方法大全

    webstorm 作为最近最火的前端开发工具,也确实对得起那个价格,但是秉着勤俭节约的传统美德,我们肯定是能省则省啊. 方法一:(更新时间:2018/1/23)v3.3 注册时,在打开的License ...

  9. SSH免密码登录,实现数据传输备份

    简单来说,就是通过ssh-keygen -t rsa命令来产生一组公私钥,私钥是id_rsa,公钥是id_rsa.pub,把公钥上传到另一台服务器对应账号的.ssh/authorized_keys,即 ...

  10. webpack中Module build failed: Unknown word (2:1)

    在新建的webpack.config.js文件中配置好style-loader和css-loader,注意顺序为:style-loader,css-loader,less-loader,postcss ...