React的React.createElement源码解析(一)
一.什么是jsx
jsx是语法糖 它是js和html的组合使用
二.为什么用jsx语法
高效定义模版,编译后使用 不会带来性能问题
三.jsx语法转化为js语法
jsx语法通过babel转化为js语法 内部调用了createElement()方法
html标签
自定义组件
React.Fragment组件
React.createElement(标签名type,属性对象config,子节点1,子节点2.....)
1.参数:标签名,属性对象,子节点 返回值:虚拟dom对象
2.标签名type类型:1.标签名字符串 2.组件(自定义组件:函数组件/class组件,react原生组件:React.Fragment等)
3.config对象:写在标签type上的属性集合
4.children:表示子节点的集合 是一个数组,比如:<ul><li>demo</li></ul> 1.ul而言 子节点:li 2.li而言 子节点demo
虚拟dom:
四,React.createElement(type,config,[...children])源码分析
作用:根据指定的第一个参数 创建一个react元素
源码解析:
- function createElement(type, config, children) {
- var propName;
- //提取保留名称
- var props = {};
- var key = null;
- var ref = null;
- var self = null;
- var source = null;
- //标签的属性不为空时 说明标签有属性值 特殊处理:把key和ref赋值给单独的变量
- if (config != null) {
- //有合理的ref
- if (hasValidRef(config)) {
- ref = config.ref;
- }
- //有合理的key
- if (hasValidKey(config)) {
- key = '' + config.key;
- }
- self = config.__self === undefined ? null : config.__self;
- source = config.__source === undefined ? null : config.__source;
- //config中剩余属性,且不是原生属性(RESERVED_PROPS对象的属性),则添加到新props对象中
- for (propName in config) {
- if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
- props[propName] = config[propName];
- }
- }
- }
- // Children can be more than one argument, and those are transferred onto
- // the newly allocated props object.
- //子元素数量(第三个参数以及之后参数都是子元素)
- var childrenLength = arguments.length - 2;
- if (childrenLength === 1) {
- props.children = children;
- } else if (childrenLength > 1) {
- var childArray = Array(childrenLength);
- //依次将children push到数组中
- for (var i = 0; i < childrenLength; i++) {
- childArray[i] = arguments[i + 2];
- }
- {
- //冻结array 返回原来的childArray且不能被修改 防止有人修改库的核心对象 冻结对象大大提高性能
- if (Object.freeze) {
- Object.freeze(childArray);
- }
- }
- props.children = childArray;
- }
- // Resolve default props (解决默认props)
- //如果defaultProps有值 则设置值 如果没有值取默认值 这个一般针对的是组件 而不是div这样的标签
- if (type && type.defaultProps) {
- var defaultProps = type.defaultProps;
- for (propName in defaultProps) {
- if (props[propName] === undefined) {
- props[propName] = defaultProps[propName];
- }
- }
- }
- {
- //一旦ref或者key存在
- if (key || ref) {
- //如果type是组件的话
- var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
- if (key) {
- defineKeyPropWarningGetter(props, displayName);
- }
- if (ref) {
- defineRefPropWarningGetter(props, displayName);
- }
- }
- }
- //props:1.config的属性值 2.children的属性(字符串/数组)3.default的属性值
- return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
- }
部分代码解析:
(1) Object.prototype.hasOwnProperty()
- //判断某一个属性是否在实例对象本身上,而不是在原型上 返回值:布尔值
- let obj = { a: 1 };
- obj.hasOwnProperty("a") //true
- obj.hasOwnProperty("toString")//false

- let obj = {
- foo: 123,
- get bar() { return '123' }
- };
- //返回对象指定某一个属性的描述对象
- Object.getOwnPropertyDescriptor(obj, 'bar')
- //返回对象所有属性的描述对象
- Object.getOwnPropertyDescriptors(obj)

返回值

- function hasValidKey(config) {
- {
- if (hasOwnProperty.call(config, 'key')) {
- var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
- if (getter && getter.isReactWarning) {
- return false;
- }
- }
- }
- return config.key !== undefined;
- }

五,ReactElement源码分析
作用:返回一个虚拟dom对象
源码:

- var ReactElement = function (type, key, ref, self, source, owner, props) {
- var element = {
- //因为react最终渲染dom时候,确保是react.createElement类型 需要判断$$typeof===REACT_ELEMENT_TYPE
- $$typeof: REACT_ELEMENT_TYPE,
- // Built-in properties that belong on the element
- type: type,
- key: key,
- ref: ref,
- props: props,
- // Record the component responsible for creating this element.
- _owner: owner
- };
- {
- // The validation flag is currently mutative. We put it on
- // an external backing store so that we can freeze the whole object.
- // This can be replaced with a WeakMap once they are implemented in
- // commonly used development environments.
- //WeakMap
- element._store = {}; // To make comparing ReactElements easier for testing purposes, we make
- // the validation flag non-enumerable (where possible, which should
- // include every environment we run tests in), so the test framework
- // ignores it.
- Object.defineProperty(element._store, 'validated', {
- configurable: false,
- enumerable: false,
- writable: true,
- value: false
- }); // self and source are DEV only properties.
- Object.defineProperty(element, '_self', {
- configurable: false,
- enumerable: false,
- writable: false,
- value: self
- }); // Two elements created in two different places should be considered
- // equal for testing purposes and therefore we hide it from enumeration.
- Object.defineProperty(element, '_source', {
- configurable: false,
- enumerable: false,
- writable: false,
- value: source
- });
- if (Object.freeze) {
- //代码性能优化:将element的一些属性配置为不可配置 提高性能
- Object.freeze(element.props);
- Object.freeze(element);
- }
- }
- return element;//返回虚拟dom对象
- };

React的React.createElement源码解析(一)的更多相关文章
- React的Component,PureComponent源码解析(二)
1.什么是Component,PureComponent? 都是class方式定义的基类,两者没有什么大的区别,只是PureComponent内部使用shouldComponentUpdate(nex ...
- React的React.createContext()源码解析(四)
一.产生context原因 从父组件直接传值到孙子组件,而不必一层一层的通过props进行传值,相比较以前的那种传值更加的方便.简介. 二.context的两种实现方式 1.老版本(React16.x ...
- React的React.createRef()/forwardRef()源码解析(三)
1.refs三种使用用法 1.字符串 1.1 dom节点上使用 获取真实的dom节点 //使用步骤: 1. <input ref="stringRef" /> 2. t ...
- React源码解析之React.Children.map()(五)
一,React.Children是什么? 是为了处理this.props.children(this.props.children表示所有组件的子节点)这个属性提供的工具,是顶层的api之一 二,Re ...
- 【vuejs深入二】vue源码解析之一,基础源码结构和htmlParse解析器
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. vuejs是一个优秀的前端mvvm框架,它的易用性和渐进式的理念可以使每一个前端开发人员感到舒服,感到easy.它内 ...
- Spring IoC源码解析——Bean的创建和初始化
Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...
- elementUi源码解析(1)--项目结构篇
因为在忙其他事情好久没有更新iview的源码,也是因为后面的一些组件有点复杂在考虑用什么方式把复杂的功能逻辑简单的展示出来,还没想到方法,突然想到element的组件基本也差不多,内部功能的逻辑也差不 ...
- Redux系列x:源码解析
写在前面 redux的源码很简洁,除了applyMiddleware比较绕难以理解外,大部分还是 这里假设读者对redux有一定了解,就不科普redux的概念和API啥的啦,这部分建议直接看官方文档. ...
- 【原创】backbone1.1.0源码解析之View
作为MVC框架,M(odel) V(iew) C(ontroler)之间的联系是必不可少的,今天要说的就是View(视图) 通常我们在写逻辑代码也好或者是在ui组件也好,都需要跟dom打交道,我们 ...
随机推荐
- RN开发-Android原生交互
在使用RN开发过程中,难免有些原生功能需要要自己来实现,下面总结一下在使用RN与原生开发交互. 1.在原生代码中定义实现类 1.1 首先继承 ReactContextBaseJaveModule抽象 ...
- C语言链表头插法逆向输出
输入:1 2 3 4 5 -1 输出:5 4 3 2 1 此题考查头链表的创建之一 :头插法.所谓头插法是从一个空链表开始,重复读入数据,生成新结点,将读入的数据存放新结点的数据域中,然后讲新结点插入 ...
- AntDesign(React)学习-12 使用Table
AntDesign(Vue)版的Table中使用图片https://www.cnblogs.com/zhaogaojian/p/11119762.html 之前在使用VUE版Table时,使用大图片时 ...
- Controller 和 Action -1
https://www.cnblogs.com/willick/p/3331521.html MVC 的每个请求都会提交到 Controller 处理.Controller 包含了对请求的逻辑处理,能 ...
- [Codechef CHSTR] Chef and String - 后缀数组
[Codechef CHSTR] Chef and String Description 每次询问 \(S\) 的子串中,选出 \(k\) 个相同子串的方案有多少种. Solution 本题要求不是很 ...
- normalization, standardization and regularization
Normalization Normalization refers to rescaling real valued numeric attributes into the range 0 and ...
- django 搭建一个投票类网站(一)
写在最前,之前零零散散的看过django,但是由于比较杂,学的云里雾里的,所以就停了一段落,但是我最近找到了一个django的书,是李建编著的django入门与实践,于是,打算照着书上的步骤来写好一个 ...
- 网页前端导出CSV,Excel格式文件
通过自己实际测试有以下几种方法 方法一通过a标签实现,把要导出的数据用“\n”和“,”拼接成一个字符串,然后把字符串放到href中,这种方法只支持chrome,firefox等非ie浏览器 html页 ...
- thinkphp中路由的基本使用
1.在application中下的config.php中 以下代码改为true // 是否开启路由 'url_route_on' => true, // 是否强制使用路由 'url_route_ ...
- 如何修改C# winform程序图标
以Visual Studio 2012 C# Winform程序为例 一.程序内部显示图标的修改方法 在窗体的属性窗口找到icon属性,设置成已经准备好的ico格式的文件,效果如下 二.程序外部显示图 ...