You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importReact,{Component}from'react';importlogofrom'./logo.svg';import'./App.css';classAppextendsComponent{render(){return(<divclassName="App"><headerclassName="App-header"><imgsrc={logo}className="App-logo"alt="logo"/><p>
Edit <code>src/App.js</code> and save to reload.
</p></header></div>);}}exportdefaultApp;console.log(<App/>)
functionComponent(props,context,updater){this.props=props;this.context=context;// If a component has string refs, we will assign a different object later.this.refs=emptyObject;// We initialize the default updater but the real one gets injected by the// renderer.this.updater=updater||ReactNoopUpdateQueue;}Component.prototype.isReactComponent={};Component.prototype.setState=function(partialState,callback){!(typeofpartialState==='object'||typeofpartialState==='function'||partialState==null) ? invariant(false,'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : void0;this.updater.enqueueSetState(this,partialState,callback,'setState');};Component.prototype.forceUpdate=function(callback){this.updater.enqueueForceUpdate(this,callback,'forceUpdate');};
functioncreateElement(type,config,children){varpropName=void0;// Reserved names are extractedvarprops={};varkey=null;varref=null;varself=null;varsource=null;······returnReactElement(type,key,ref,self,source,ReactCurrentOwner.current,props);}
这里又返回了一个ReactElement方法,再顺着往下找:
varReactElement=function(type,key,ref,self,source,owner,props){varelement={// This tag allows us to uniquely identify this as a React Element$$typeof: REACT_ELEMENT_TYPE,// Built-in properties that belong on the elementtype: type,key: key,ref: ref,props: props,// Record the component responsible for creating this element._owner: owner};······returnelement;};
前言
react使用也有一段时间了,大家对这个框架褒奖有加,但是它究竟好在哪里呢?
让我们结合它的源码,探究一二!(当前源码为react16,读者要对react有一定的了解)
回到最初
根据react官网上的例子,快速构建react项目
打开项目并跑起来以后,暂不关心项目结构及语法糖,看到
App.js
里,这是一个基本的react组件 我们console一下,看看有什么结果。可以看到,
<App/>
组件其实是一个JS对象,并不是一个真实的dom。上面有我们很熟悉的
props
,ref
,key
,我们稍微修改一下console,看看有什么变化。可以看到,
props
,key
都发生了变化,值就是我们赋予的值,props
中嵌套了children属性。可是为什么我们嵌入的是div,实际上却是一个对象呢?打开源码
首先打开
index.js
可以知道目前用上的是
./cjs/react.development.js
,直接打开文件。根据最初的代码,我们组件
<App/>
用到了React.Component。找到React暴露的接口:接着找到
Component: Component
方法,上面就是一些简单的构造函数,也可以看到,我们常用的setState是定义在原型上的2个方法。
至此,一个
<App/>
组件已经有一个大概的雏形:到此为止了吗?这看了等于没看啊,究竟组件是怎么变成div的?render吗?
可是全局搜索,也没有一个function是render啊。
原来,我们的jsx语法会被
babel
编译的。这下清楚了,还用到了
React.createElement
通过
createElementWithValidation
,可以看到,return了一个element,这个element又是继承自
createElement
,接着往下找:这里又返回了一个
ReactElement
方法,再顺着往下找:诶,这里好像返回的就是
element
对象,再看我们最初的<App/>
的结构,是不是很像React.createElement 、 createElementWithValidation 、 createElement 、 ReactElement,通过这些方法,我们用class声明的React组件在变成真实dom之前都是
ReactElement
类型的js对象createElementWithValidation
:createElement
:ReactElement
:ReactElement就比较简单了,创建一个element对象,参数里的type、key、ref、props、等放进去,然后return了。最后调用Object.freeze使对象不可再改变。
组件的挂载
我们上面只是简单的探究了
<App/>
的结构和原理,那它究竟是怎么变成真实dom的呢我们接着用babel编译一下:
原来
ReactDOM.render
调用的是render方法,一样,找暴露出来的接口。它返回的是一个
legacyRenderSubtreeIntoContainer
方法,这次我们直接打上console.log这是打印出来的结果,
legacyRenderSubtreeIntoContainer
这个方法除主要做了两件事:
源码暂时只读到了这里,关于React16.1~3的新功能,以及新的生命周期的使用和原理、
Fiber
究竟是什么,我们将在后续文章接着介绍。广而告之
本文发布于薄荷前端周刊,欢迎Watch & Star ★,转载请注明出处。
欢迎讨论,点个赞再走吧 。◕‿◕。 ~
The text was updated successfully, but these errors were encountered: