一、一个真正的react组件编译后长啥样?

我们瞎几把解读了react 虚拟dom对象是怎么生成的,生成了一个什么样的解构。一个react组件不光由若干个这些嵌套的虚拟dom对象组成,还包括各种生命周期钩子、自定义方法、事件等组成

下面让我们继续探索

react组件写法:

 // 一个再普通不过的react组件写法

 mport React,{Component} from 'react';
import Header from '../components/header';
class Home extends Component {
constructor(props){
super(props);
}
componentWillMount(){
console.log('willMount');
}
handleClickEvent(){
console.log('click');
}
render(){
let {name} = this.props;
return (
<div ref="home">
<Header kk="js"/>
<div>主页:{name}</div>
<div>
<p onClick={this.handleClickEvent}>哈哈哈哈</p>
</div>
</div>
)
}
} export default Home;

react组件被babel-preset-react编译后

 var Home = function (_Component) {
_inherits(Home, _Component); function Home(props) {
_classCallCheck(this, Home); return _possibleConstructorReturn(this, (Home.__proto__ || Object.getPrototypeOf(Home)).call(this, props));
} _createClass(Home, [{
key: 'componentWillMount',
value: function componentWillMount() {
console.log('willMount');
}
}, {
key: 'handleClickEvent',
value: function handleClickEvent() {
console.log('click');
}
}, {
key: 'render',
value: function render() {
var name = this.props.name; return _react2.default.createElement(
'div',
{ ref: 'home' },
_react2.default.createElement(_header2.default, { kk: 'js' }),
_react2.default.createElement(
'div',
null,
'\u4E3B\u9875:',
name
),
_react2.default.createElement(
'div',
null,
_react2.default.createElement(
'p',
{ onClick: this.handleClickEvent },
'\u54C8\u54C8\u54C8\u54C8'
)
)
);
}
}, {
key: '__reactstandin__regenerateByEval',
// @ts-ignore
value: function __reactstandin__regenerateByEval(key, code) {
// @ts-ignore
this[key] = eval(code);
}
}]); return Home;
}(_react.Component);

通过看编译后的代码,我们得出以下关键词线索: React.Component

二、React.Component 又干了什么

Component来自于 ReactBaseClasses.js  找到他!

import {Component, PureComponent} from './ReactBaseClasses';
function Component(props, context, updater) {
this.props = props; // 眼熟的props
this.context = context; // context
this.refs = emptyObject; // 初始化refs
this.updater = updater || ReactNoopUpdateQueue;
} Component.prototype.isReactComponent = {};
// 经典的setState 方法
Component.prototype.setState = function(partialState, callback) {
...
};
// 强制重绘
Component.prototype.forceUpdate = function(callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

通过阅读代码,我们发现Component这个类的构成其实并不复杂,但其中的updater是一个很重要的东西,不过今天略过不表,脱离生命周期及dom渲染看updater没有任何意义,以后再说

同样setState也以后再说

通过js中的extends, 本文中的home组件获得了Component类中的所有属性和方法,我们再看源码,看看babel是如何拆解react组件生命周期的

三、defineProperty 的一顿猛操作

babel在解析jsx的时候自己定义了一堆模拟es6 extends、 class 、super的一堆东西

通过查看解析后的源码,我们可以知道其中奥秘

var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}(); function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ =
superClass;
}

一个仿造的继承,一个仿造的createClass

前者通过_inherits(Home,Component) 将 Component的prototype 赋予到Home上,使Home拥有了setState方法等等

后者通过  Object.defineProperty 将key-value形式的对象 赋予到 Home.prototype上

回首看被babel表一出来的react组件,那些钩子函数、自定义方法都被搞成了一个个key-value形式的对象,通过_createClass 给绑定到了Home类中

这样一个组件类就做好了,这个组件类的prototype里面有自定义函数、生命周期钩子函数、render方法

然后就是通过createElement又再次的封装成react 虚拟dom 被放到ReactDOM 中等待render

// 编译前
ReactDOM.render(
<div>
<Home name="home"/>
</div>
,
document.getElementById('app')
); // 编译后
_reactDom2.default.render(_react2.default.createElement(
'div',
null,
_react2.default.createElement(_home2.default, { name: 'home' })
), document.getElementById('app'));

只不过这种虚拟dom和其他的不太一样,这种的对象里面的type类型是函数,而不是字符串罢了。所以可见 createElement返回对象的type不一定是字符串,是一切皆有可能

要知render中发生了什么,请听下回分解

四、本期留坑

setState 的解读,还没搞....

React 16 源码瞎几把解读 【二】 react组件的解析过程的更多相关文章

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

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

  2. React 16 源码瞎几把解读 【一】 从jsx到一个react 虚拟dom对象

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

随机推荐

  1. 【插件】LinqToExcel常用对象

    1.ExcelQueryFactory对象(1)获取工作表名集合IEnumerable<string> GetWorksheetNames() //获取工作薄中的工作表名foreach ( ...

  2. iOS----MRC(手动内存管理)

    1.MRC是什么,有什么用? 在苹果开发中,我们是没有垃圾回收机制的.所以在ARC推出之前,我们苹果开发程序员需要通过手动代码的形式尽量严密的管理我们的App的内存: ---------------- ...

  3. uoj54-bzoj3434-时空穿梭

    题意 在一个 \(n\) 维空间中,求一个点可以用一个 \(n\) 维向量 \((x_1,x_2,\dots x_n)\) 表示.现在要选出 \(c\) 个点,有三个限制: 设 \(x_i\) 表示任 ...

  4. request之setAtrribute

    当在servlet中有request.SetAtrribute("AtriruteName",AtrributeValue)语句时,在jsp页面获取AtrributeValue有两 ...

  5. Qt Widgets、QML、Qt Quick的区别

    Qt Widgets.QML.Qt Quick的区别 简述 看了之前关于 QML 的一些介绍,很多人难免会有一些疑惑: Q1:QML 和 Qt Quick 之间有什么区别? Q2:QtQuick 1. ...

  6. 【比赛】HNOI2018 毒瘤

    虚树+dp 直接看zlttttt的强大题解 zlttttt的题解看这里 #include<bits/stdc++.h> #define ui unsigned int #define ll ...

  7. 【Luogu3676】小清新数据结构题(动态点分治)

    [Luogu3676]小清新数据结构题(动态点分治) 题面 洛谷 题解 先扯远点,这题我第一次看的时候觉得是一个树链剖分+线段树维护. 做法大概是这样: 我们先以任意一个点为根,把当前点看成是一棵有根 ...

  8. 【BZOJ3625/CF438E】小朋友和二叉树(多项式求逆,多项式开方)

    [BZOJ3625/CF438E]小朋友和二叉树(多项式求逆,多项式开方) 题面 BZOJ CodeForces 大致题意: 对于每个数出现的次数对应的多项式\(A(x)\) 求\[f(x)=\fra ...

  9. 强大工具psexec工具用法简介

    原文链接地址:https://www.cnblogs.com/boltkiller/articles/4791307.html psexec是sysinternals的一款强大的软件,通过他可以提权和 ...

  10. 洛谷 P3539 [POI2012]ROZ-Fibonacci Representation 解题报告

    P3539 [POI2012]ROZ-Fibonacci Representation 题意:给一个数,问最少可以用几个斐波那契数加加减减凑出来 多组数据10 数据范围1e17 第一次瞬间yy出做法, ...