Heim >Web-Frontend >js-Tutorial >Analyse des ersten Renderings von React (reines DOM-Element)
Der Inhalt dieses Artikels befasst sich mit der Analyse des ersten Renderings von React (reine DOM-Elemente). Ich hoffe, dass er für Sie hilfreich ist.
React ist eine sehr große Bibliothek, da ReactDom und ReactNative gleichzeitig berücksichtigt werden müssen, ebenso wie Server-Rendering usw., der Code weist einen hohen Abstraktionsgrad und eine sehr tiefe Verschachtelungsebene auf Der Quellcode ist sehr schwierig. Beim Erlernen des React-Quellcodes hat mir diese Artikelserie am meisten geholfen, daher habe ich beschlossen, auf der Grundlage dieser Artikelserie über mein Verständnis zu sprechen. In diesem Artikel werden viele Beispiele aus dem Originaltext verwendet. Wenn Sie das ursprüngliche Gefühl erleben möchten, wird empfohlen, den Originaltext zu lesen.
Diese Artikelserie basiert auf React 15.4.2.
Wenn wir React-Projekte schreiben, schreiben wir sie normalerweise direkt in JSX-Form, und JSX wird schließlich von Babel kompiliert , wird das HTML-Tag in die Funktionsform von React.createElement konvertiert. Wenn Sie ein tieferes Verständnis haben möchten, können Sie diesen Artikel lesen, den ich zuvor geschrieben habe: Virtuelles DOM, das Sie nicht kennen (1): Einführung in virtuelles Dom. Die h-Funktion im Artikel ist standardmäßig React.createElement, wenn sie nicht in Babel konfiguriert ist.
Im Folgenden werfen wir einen Blick darauf, wie React anhand des einfachsten Beispiels gerendert wird
ReactDOM.render( <h1>hello world</h1>, document.getElementById('root') );
Nach der JSX-Kompilierung wird es so aussehen
ReactDOM.render( React.createElement( 'h1', { style: { "color": "blue" } }, 'hello world' ), document.getElementById('root') );
Wer zuerst kommt, schaut es euch an der Quellcode von React.createElement
.
// 文件位置:src/isomorphic/React.js var ReactElement = require('ReactElement'); ... var createElement = ReactElement.createElement; ... var React = { ... createElement: createElement, ... } module.exports = React;
Die endgültige Implementierung muss angesehen werden ReactElement.createElement
:
// 文件位置:src/isomorphic/classic/element/ReactElement.js ReactElement.createElement = function (type, config, children) { ... // 1. 将过滤后的有效的属性,从config拷贝到props if (config != null) { ... for (propName in config) { if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { props[propName] = config[propName]; } } } // 2. 将children以数组的形式拷贝到props.children属性 var childrenLength = arguments.length - 2; if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { var childArray = Array(childrenLength); for (var i = 0; i <p> führt im Wesentlichen nur drei Dinge aus: </p><ol class=" list-paddingleft-2"> <li><p> filtert die gültigen Attribute und kopiert sie von config zu props</p></li> <li><p>Kinder in das props.children-Attribut in Form eines Arrays kopieren</p></li> <li><p>Standardattributzuweisung</p></li> </ol> ist <p>. Werfen wir einen Blick darauf, was es tut<code>ReactElement</code></p><pre class="brush:php;toolbar:false">// 文件位置:src/isomorphic/classic/element/ReactElement.js var ReactElement = function (type, key, ref, self, source, owner, props) { var element = { // This tag allow us to uniquely identify this as a React Element $$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, }; ... return element; };Am Ende gibt es nur ein einfaches Objekt zurück. Der Aufrufstapel sieht so aus:
React.createElement |=ReactElement.createElement(type, config, children) |-ReactElement(type,..., props)Das hier generierte ReactElement heißt
und wird als Parameter an ReactDom.render übergeben. ReactElement[1]
// 文件位置:src/renderers/dom/client/ReactMount.js _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) { ... var nextWrappedElement = React.createElement( TopLevelWrapper, { child: nextElement } ); ... var component = ReactMount._renderNewRootComponent( nextWrappedElement, container, shouldReuseMarkup, nextContext )._renderedComponent.getPublicInstance(); ... return component; }, ... var TopLevelWrapper = function () { this.rootID = topLevelRootCounter++; }; TopLevelWrapper.prototype.isReactComponent = {}; TopLevelWrapper.prototype.render = function () { return this.props.child; }; TopLevelWrapper.isReactTopLevelWrapper = true; ... _renderNewRootComponent: function ( nextElement, container, shouldReuseMarkup, context ) { ... var componentInstance = instantiateReactComponent(nextElement, false); ... return componentInstance; },Hier wird es wieder Another genannt Datei instanziiertReactComponent:
// 文件位置:src/renders/shared/stack/reconciler/instantiateReactComponent.js function instantiateReactComponent(node, shouldHaveDebugID) { var instance; ... instance = new ReactCompositeComponentWrapper(element); ... return instance; } // To avoid a cyclic dependency, we create the final class in this module var ReactCompositeComponentWrapper = function (element) { this.construct(element); }; Object.assign( ReactCompositeComponentWrapper.prototype, ReactCompositeComponent, { _instantiateReactComponent: instantiateReactComponent, } );Dadurch wird eine andere Datei ReactCompositeComponent:
// 文件位置:src/renders/shared/stack/reconciler/ReactCompositeComponent.js var ReactCompositeComponent = { construct: function (element) { this._currentElement = element; this._rootNodeID = 0; this._compositeType = null; this._instance = null; this._hostParent = null; this._hostContainerInfo = null; // See ReactUpdateQueue this._updateBatchNumber = null; this._pendingElement = null; this._pendingStateQueue = null; this._pendingReplaceState = false; this._pendingForceUpdate = false; this._renderedNodeType = null; this._renderedComponent = null; this._context = null; this._mountOrder = 0; this._topLevelWrapper = null; // See ReactUpdates and ReactUpdateQueue. this._pendingCallbacks = null; // ComponentWillUnmount shall only be called once this._calledComponentWillUnmount = false; if (__DEV__) { this._warnedAboutRefsInRender = false; } } ... }aufgerufen. Wir verwenden
, um die hier generierte Komponente der obersten Ebene darzustellen. ReactCompositeComponent[T]
ReactDOM.render |=ReactMount.render(nextElement, container, callback) |=ReactMount._renderSubtreeIntoContainer() |-ReactMount._renderNewRootComponent( nextWrappedElement, // scr:------------------> ReactElement[2] container, // scr:------------------> document.getElementById('root') shouldReuseMarkup, // scr: null from ReactDom.render() nextContext, // scr: emptyObject from ReactDom.render() ) |-instantiateReactComponent( node, // scr:------------------> ReactElement[2] shouldHaveDebugID /* false */ ) |-ReactCompositeComponentWrapper( element // scr:------------------> ReactElement[2] ); |=ReactCompositeComponent.construct(element)Die hierarchische Struktur zwischen den Komponenten sieht so aus:
Nachdem die Komponente der obersten Ebene erstellt wurde, besteht der nächste Schritt darin, batchedMountComponentIntoNode (Methode _renderNewRootComponent von ReactMount) aufzurufen, um die Seite zu rendern.
Das obige ist der detaillierte Inhalt vonAnalyse des ersten Renderings von React (reines DOM-Element). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!