一、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. SPOJ4717——Grid Points in a Triangle

    题目的意思很简单.就是要你求出斜率为a/b的一个点在原点,一条边为x=n的RT三角形里面有多少个整数点? 看完题目后依然没有思路,依然去看各个神牛写的题解.后来才反应过来. 题目的正解应该是这样的.递 ...

  2. BZOJ 1264 基因匹配(DP+线段树)

    很有意思的一道题啊. 求两个序列的最大公共子序列.保证每个序列中含有1-n各5个. 如果直接LCS显然是TLE的.该题与普通的LCS不同的是每个序列中含有1-n各5个. 考虑LCS的经典DP方程.dp ...

  3. Python 模板 Jinja2

    Python 模板 Jinja2 模板 要了解Jinja2,就需要先理解模板的概念.模板在Python的web开发中广泛使用,它能够有效的将业务逻辑和页面逻辑分开,使代码可读性更强.更加容易理解和维护 ...

  4. Contest 7

    A:搜索好难啊根本不会啊. B:原题都能写挂没救了啊.考虑求出每个数作为最小值时能向左向右扩展到的最远位置,那么这段区间里的所有数就不可能作为唯一的最小值成为最优解了,否则假设可以的话这段区间里的数都 ...

  5. InnoDB事务日志(redo log 和 undo log)详解

    数据库通常借助日志来实现事务,常见的有undo log.redo log,undo/redo log都能保证事务特性,undolog实现事务原子性,redolog实现事务的持久性. 为了最大程度避免数 ...

  6. ubuntu adduser

    ubuntu adduser 添加用户 hexan 到目录 /home/hexan 下.$ sudo adduser hexan -home /home/hexan 添加一个普通用户adduser [ ...

  7. py2exe使用总结

    假如你用python写了个小程序,想给别人用或者给别人演示,但他电脑里没装python.wxpython等,这时候你可以试试py2exe,它是一个将python脚本转换成windows上的可执行程序( ...

  8. hihoCoder #1639 图书馆

    题目大意 给定 $n$($1\le n\le 1000$)个正整数 $a_1, a_2, \dots, a_n$($a_i \le 10^{12}$),令 $s$ 为这 $n$ 个数之和.求 $$ \ ...

  9. SpringBoot多数据源配置事务

    除了消费降级,这将会是娱乐继续下沉的一年. 36氪从多个信源处获悉,资讯阅读应用趣头条已经完成了腾讯领投的Pre-IPO轮融资,交易金额预计达上亿美元,本轮融资估值在13-15亿美金之间:完成此轮融资 ...

  10. 【noip2018】【luogu5021】赛道修建

    题目描述 C 城将要举办一系列的赛车比赛.在比赛前,需要在城内修建 mm 条赛道. C 城一共有 nn 个路口,这些路口编号为 1,2,…,n1,2,…,n,有 n-1n−1 条适合于修建赛道的双向通 ...