React entrance Detailed

Source: Internet
Author: User
Tags hasownproperty

When using react to build an application, we always have a step to render the build or virtual DOM elements to the real DOM, the task to the browser, and then the steps of layout and paint, and this function is React.render (). First look at the interface definition of the function:

Reactcomponent render (reactelement element, domelement container, [function callback])

Receives 2-3 parameters and returns an object of type Reactcomponent, and executes a callback when the component is added to the DOM. Here the two react types--reactcomponent and reactelement are involved, with an emphasis on analysis.

Reactelement Type Interpretation

The Reactelement type is created from the function react.createelement (), and the interface is defined as follows:

Reactelement createelement (string/reactclass type, [object props], [children ...])

The first parameter can accept a string (such as "P", "div", and so on) or Reactclass, the second parameter is the passed argument, and the third is a child element, which can be a string and a reactelement.

The following focuses on the specific implementation of createelement:

Reactelement.createelement = function (type, config, children) {var propname;//Reserved names is Extractedvar props = {};  var key = Null;var ref = null;if (config! = null) {ref = Config.ref = = = undefined? null:config.ref;key = Config.key = = = Undefined? Null: ' + config.key;//Remaining Properties is added to a new props objectfor (propname in config) {if (CONFIG.HASOWNP Roperty (propname) &&! Reserved_props.hasownproperty (propname)) {Props[propname] = Config[propname];}}} Children can is more than one argument, and those is transferred onto//the newly allocated props Object.var childrenl Ength = arguments.length-2;if (Childrenlength = = = 1) {Props.children = children;} else if (Childrenlength > 1) {var c Hildarray = Array (childrenlength); for (var i = 0; i < childrenlength; i++) {Childarray[i] = arguments[i + 2];} Props.children = Childarray;} Resolve default Propsif (type && type.defaultprops) {var defaultprops = type.defaultprops;for (propname in DEFA UltpRops) {if (typeof props[propname] = = = ' undefined ') {props[propname] = Defaultprops[propname];}}} return new Reactelement (type,key,ref,reactcurrentowner.current,reactcontext.current,props);}; var reactelement = function (type, key, ref, owner, context, props) {//built-in properties that belong on the elementthis. Type = Type;this.key = Key;this.ref = ref;//Record The component responsible for creating this element.this._owner = Owne r;//todo:deprecate Withcontext, and then the context becomes accessible//through the Owner.this._context = Context;if ( "Production"!== Process.env.NODE_ENV) {//the validation flag and props are currently mutative. We put them on//an external backing store so that we can freeze the whole object.//this can is replaced with a weakmap o nCE They is implemented in//commonly used development Environments.this._store = {Props:props, originalprops:assign ({} , props)};//to make comparing reactelements easier for testing purposes, we make//the validation flagNon-enumerable (where possible, which should//include every environment we run tests in), so the test framework//ignores it.try {object.defineproperty (this._store, ' validated ', {configurable:false,enumerable:false,writable:true});} catch (x) {}this._store.validated = false;//we ' re not allowed to set props directly on the object so we early//return an D rely on the prototype membrane to forward to the backing//Store.if (usemutationmembrane) {object.freeze (this); return;} }this.props = props;};

  

This method is implemented in Reactelement.js, where the arguments are saved first, where ref and key are special, ref is used for the parent component to refer to the real dom,key of the subassembly for the harmonic algorithm, to determine whether the component is update or remove; save children to props , and props is mixin based on whether the type has a Defaultprops attribute, and the Reactelement instance is created last. Where Reactelement has an instance property of _owner, which is used to save the component to which it belongs.

Reactelement's prototype object has only one simple method for judging whether it is a Reactelement object, and there is no additional method.

In summary, we can see that Reactelement has 4 properties: Type,ref,key,props, and lightweight, no state, is a virtualized DOM element.

Reactclass Type Interpretation

The core of react is the reactelement type, but the essence is indeed reactcomponent, the component. But the creation of the component is not simple, we create the Reactclass class through React.createclass, it is reactcomponent constructor , different from normal object creation, the creation of the component is taken over by react, That is, we do not need to instantiate it (new MyComponent ()). The reactcomponent is stateful with respect to the reactelement, and the interface definition is first seen:

Reactclass Createclass (Object specification)

The passed spec parameter must contain the Render method for rendering the virtual Dom,render return reactelement type, and there are getinitialstate and life-cycle methods that can be defined as needed.

The following is an in-depth analysis based on the implementation of Createclass:

Createclass:function (spec) {var Constructor = function (props, context) {//Wire up Auto-bindingif (THIS.__REACTAUTOBINDM AP) {Bindautobindmethods (this);} This.props = Props;this.context = Context;this.state = null;//reactclasses doesn ' t has constructors. Instead, they use the//getinitialstate and Componentwillmount methods for Initialization.var initialstate = This.getiniti Alstate? This.getinitialstate (): Null;this.state = initialstate;}; Constructor.prototype = new Reactclasscomponent (); Constructor.prototype.constructor = Constructor;injectedmixins.foreach (Mixspecintocomponent.bind (NULL, Constructor) mixspecintocomponent (Constructor, spec);//Initialize The Defaultprops property after all Mixins has been Mergedif (constructor.getdefaultprops) {constructor.defaultprops = Constructor.getdefaultprops ();} Reduce time spent doing lookups by setting these on the Prototype.for (var methodName in reactclassinterface) {if (! Constructor.prototype[methodname]) {Constructor.prototype[methoDNAME] = null;}} Legacy hookconstructor.type = Constructor;return Constructor;} Constructor's prototype var reactclasscomponent = function () {};//Assign is similar to Mixinassign (Reactclasscomponent.prototype, Reactcomponent.prototype,reactclassmixin)///Mixin to Constructor on the prototype function mixspecintocomponent (Constructor, spec {if (!spec) {return;} var proto = constructor.prototype;//by handling mixins before no other properties, we ensure the same//chaining order I S applied to methods with Define_many policy, whether//Mixins is listed before or after these methods in the Spec.if (SP Ec.hasownproperty (Mixins_key)) {reserved_spec_keys.mixins (Constructor, spec.mixins);} for (var name in spec) {if (!spec.hasownproperty (name)) {continue;} if (name = = = Mixins_key) {//We have already handled mixins in a special case abovecontinue;} var property = Spec[name];validatemethodoverride (proto, name), if (Reserved_spec_keys.hasownproperty (name)) {RESERVED _spec_keys[name] (Constructor, property);} else {//Setup methods on prototype://the following member methods should not being automatically bound://1. Expected Reactclass methods (in the "interface").//2. Overridden methods (that's were mixed in). var isreactclassmethod =reactclassinterface.hasownproperty (name); var isalreadydefined = Proto.hasownproperty (name); var Markeddontbind = Property && Property.__reactdontbind;var Isfunction = typeof Property = = = ' function '; var shouldautobind =isfunction &&!isreactclassmethod &&! isalreadydefined &&!markeddontbind;if (shouldautobind) {if (!proto.__reactautobindmap) {proto.__ Reactautobindmap = {};} Proto.__reactautobindmap[name] = property;proto[name] = property;} else {if (isalreadydefined) {var specpolicy = reactclassinterface[name];//for methods which is defined more than once, C All the existing//methods before calling the new property, merging if appropriate.if (specpolicy = = = Specpolicy.define_ma ny_merged) {Proto[name] = createmergedresultfunction (Proto[name], property);} elseif (Specpolicy = = = Specpolicy.define_many) {Proto[name] = createchainedfunction (Proto[name], property);}}  else {Proto[name] = property;if ("Production"!== Process.env.NODE_ENV) {//ADD verbose displayName to the function, which Helps when looking//@ profiling Tools.if (typeof property = = = ' function ' && spec.displayname) {Proto[name].disp Layname = Spec.displayname + ' _ ' + Name;}}}}}

Createclass returns a constructor constructor whose prototype is a newreactclasscomponent () object that has a method of Mixin component (the method of the object of the Mixins property in the Spec object) and Reactcomponent methods (SetState and ForceUpdate), and in Mixspecintocomponent (Constructor, spec) Method binds the method implemented in the spec to the constructor prototype, where the non-react provided methods (that is, some function functions or event handlers for individual implementations) are stored on the __reactautobindmap property of the prototype. Finally, set the Defaultprops and type of Constructor (Constructor.type = Constructor).

As mentioned in the previous section, the first parameter of createelement can be reactclass, so the type and Defaultprops attributes are given on the constructor implementation.

Entrance to React-react.render ()

React.render implementation is in the Reactmount, we through the source for further analysis.

Render:function (Nextelement, container, callback) {var prevcomponent = Instancesbyreactrootid[getreactrootid ( Container)];if (prevcomponent) {var prevelement = prevcomponent._currentelement;if (Shouldupdatereactcomponent ( Prevelement, nextelement) {return reactmount._updaterootcomponent (prevcomponent,nextelement,container,callback). Getpublicinstance ();} else {Reactmount.unmountcomponentatnode (container);}} var reactrootelement = Getreactrootelementincontainer (container); var containerhasreactmarkup =reactrootelement & & Reactmount.isrenderedbyreact (reactrootelement); var shouldreusemarkup = Containerhasreactmarkup &&! Prevcomponent;var component = Reactmount._rendernewrootcomponent (Nextelement,container,shouldreusemarkup). Getpublicinstance (); if (callback) {Callback.call (component);} return component;}

  

If the reactelement is mounted for the first time, it can be added directly, and if it has been previously mounted, Instancesbyreactrootid gets the old component container before rendering, that is, prevcomponent, The container is obtained by obtaining the firstchild of the object, and the corresponding ID is obtained from the cache, and is prevcomponent according to the ID. Each Component object has a corresponding virtual DOM, reactelement, through Shouldupdatereactcomponent (Prevelement, Nextelement) to determine whether the component is being update or delete.

The specific shouldupdatereactcomponent comparison algorithm is: If the prevelement type is string or number, then the nextelement type is string or number is true If Prevelement and Nextelement are object, and the key and type properties are the same, then Prevelement._owner = = Nextelement._owner equals True, otherwise false.

If an update is required, call Reactmount. The _updaterootcomponent function reconciliation and returns the component, otherwise the component is deleted, and all child elements of the container are deleted. The shouldreusemarkup is then judged to be false for the initial mount of the reactelement. Finally, the reactelement is rendered to the DOM by calling the _rendernewrootcomponent method, the corresponding Reactcomponent object is fetched, the callback is executed and the Component object is returned.

For the _rendernewrootcomponent method, the component is instantiated by calling Instantiatereactcomponent (Nextelement, NULL), and the component is registered in the Reactmount cache. Executes the update reactupdates.batchedupdates in bulk and eventually inserts the virtual node into the DOM through the _mountimageintonode method.

So far, the more important method in react is explained. The next step is to analyze the instantiation process of the component, so stay tuned.

React entrance Detailed

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.