一、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. stm32中使用#pragma pack(非常有用的字节对齐用法说明)

    #pragma pack(4)   //按4字节对齐,但实际上由于结构体中单个成员的最大占用字节数为2字节,因此实际还是按2字节对齐 typedef struct { char buf[3];//bu ...

  2. bzoj2301-Problem b

    题意 \(T\le 5\times 10^4\) 次询问,每次询问 \(a,b,c,d,k\le 5\times 10^4\),求 \[ \sum _{i=a}^b\sum _{j=c}^d[gcd( ...

  3. bzoj4754[JSOI2016]独特的树叶

    这个题....别人写得怎么都....那么短啊? 我怎么....WA了好几次啊....怎么去loj扒了数据才调出来啊? 这个算法...怎么我还是不知道对不对啊 怎么回事啊怎么回事啊怎么回事啊? 请无视上 ...

  4. 聊聊flink的CsvTableSource

    序 本文主要研究一下flink的CsvTableSource TableSource flink-table_2.11-1.7.1-sources.jar!/org/apache/flink/tabl ...

  5. 【BZOJ1491】【NOI2007】社交网络(最短路,动态规划)

    [BZOJ1491][NOI2007]社交网络(最短路,动态规划) 题面 BZOJ 洛谷 图片是假的,只能到OJ上看 Description 在社交网络(socialnetwork)的研究中,我们常常 ...

  6. CODECHEF Chef and Churus 解题报告

    [CODECHEF]Chef and Churus Description 有一个长度为\(n\)的数组\(A\),有\(n\)个函数,第\(i\)个函数的值为\(\sum_{j=l_i}^{r_i} ...

  7. 解题:POI 2012 Cloakroom

    题面 首先,单独处理每个询问复杂度显然不可承受,还是考虑通过排序使得限制更容易达到:按照$a$将物品排序,按照$m$将询问排序,这样肯定是要不断添加物品才能达到要求,顺着做一遍就行了 然后发现$b$的 ...

  8. [学习笔记]Min-25筛

    %%yyb %%zsy 一. 基本操作:筛1~N中的素数个数.n=1e9 设F(M,j)表示,2~M的所有数中,满足以下条件之一的数的个数:①x是质数②x最小质因子大于(注意是大于没有等号)$P_j$ ...

  9. [转载]DataView详解

    表示用于排序.筛选.搜索.编辑和导航的 DataTable 的可绑定数据的自定义视图. DataView的功能类似于数据库的视图,他是数据源DataTable的封装对象,可以对数据源进行排序.搜索.过 ...

  10. reset password for local admin on Windows2016 by Powershell

    上脚本吧,找半天 $password = "yourpassword" $pwd = $password | ConvertTo-SecureString -asPlainText ...