Heim  >  Artikel  >  Web-Frontend  >  Erkundung der internen Mechanismen von React

Erkundung der internen Mechanismen von React

一个新手
一个新手Original
2017-10-25 15:06:311907Durchsuche

Erkundung der internen Mechanismen von React – React-Komponente und -Element

Dieser Artikel ist relativ einfach, aber er ist entscheidend für den Einstieg in die internen Mechanismen und Implementierungsprinzipien von React. Es kann als Einführung für eine ausführliche Erklärung in der Zukunft angesehen werden:

React Component Render => React.createElement => Dom

Sie können diesen Artikel direkt überspringen.

Eine kokette Frage von Google-Ingenieuren

Vor einigen Monaten veröffentlichte Googles Front-End-Entwicklungsexperte Tyler McGinnis einen solchen Tweet auf seinem persönlichen Twitter-Account und löste damit eine Diskussion über React-Komponenten aus.

Erkundung der internen Mechanismen von React

Die von ihm aufgeworfene Frage lautet: Wie im obigen Code Das Reaktionskomponentensymbol erscheint direkt im Code. Was zählt es?

Die verfügbaren Optionen sind:

  • A. Komponentendeklaration

  • B. Komponentenaufruf

  • C. Komponenteninstanziierung

  • D. Eine Komponente einfach verwenden

Interessanterweise unter den Entwicklern Wer antwortete:

  • 15 % wählten Option A;

  • 8 % wählten Option A, Punkt B;

    45 % wählten Punkt C;
  • 32 % wählten Punkt D;
  • Für Front-End-Ingenieure mit Erfahrung in der React-Entwicklung: Das Problem ist eigentlich leicht zu verstehen. Der Schlüssel ist:
  • Wirklich verstehen, wie React Elements, React Components und die JSX-Abstraktionsschicht React verbinden.
Natürlich müssen Sie auch einige einfache interne Arbeitsmechanismen von React verstehen.

Dieser Artikel führt Sie dazu, das Geheimnis dieser JSX-Abstraktionsschicht und des React Reconciliation

-Prozesses zu untersuchen.

Was genau sind React und React Element?

Kehren wir zum Anfang zurück und denken über die originellste Frage nach: Was genau ist React?

Kurz gesagt,

React ist eine Bibliothek zum Erstellen von Benutzeroberflächen.

React ist eine Klassenbibliothek (Framework. ..was auch immer... ). Egal wie komplex React selbst ist, egal wie groß sein Ökosystem ist,

Building Views
ist immer sein Kern. Mit diesen Informationen im Hinterkopf kommen wir nun zum ersten Konzept des Tages –

React Element. Einfach ausgedrückt beschreibt React Element die Dinge, die „Sie“ auf dem Bildschirm sehen möchten.

Abstrakt gesehen ist das React Element-Element ein Objekt, das einen Dom-Knoten beschreibt.

Bitte beachten Sie meinen Wortlaut – „

Beschreibung

“, da React Element nicht das ist, was Sie tatsächlich auf dem Bildschirm sehen. Es handelt sich vielmehr um eine Sammlung von Beschreibungen realer Dinge. Was existiert, ist vernünftig. Werfen wir einen Blick auf die Bedeutung der Existenz von React Element und warum es ein solches Konzept gibt:

JavaScript-Objekte sind sehr leichtgewichtig. Durch die Verwendung von Objekten als React-Elemente kann React diese Elemente problemlos erstellen oder zerstören, ohne sich zu viele Gedanken über die Betriebskosten machen zu müssen Die Fähigkeit, virtuelle Dom zu analysieren. Die Leistungsvorteile der Aktualisierung eines virtuellen Doms (im Vergleich zu einem echten Dom) bei Änderungen sind erheblich.
  • Um das Objekt (oder React-Element) zu erstellen, beschreiben wir den Dom-Knoten. Wir können die React.createElement-Methode verwenden:
  • Hier das React Die .createElement-Methode akzeptiert drei Parameter:

Eine Zeichenfolge, die den Tag-Namen beschreibt (p, span usw.);

const element = React.createElement( 
  'p', 
  {id: 'login-btn'}, 
  'Login'
)

Attribute, die das aktuelle Das React-Element muss ;
  • Der Inhalt haben, der durch das aktuelle React-Element oder ein untergeordnetes Element ausgedrückt werden soll.
  • Nachdem die obige React.createElement-Methode aufgerufen wurde, wird ein Javascript-Objekt zurückgegeben:
  • Wenn wir dann die ReactDOM.render-Methode verwenden, wird dies der Fall sein Beim Rendern in den echten DOM oben erhalten Sie:

und dies ist der echte Dom-Knoten.

Bisher gibt es keine schwer verständlichen Konzepte.
{ 
  type: 'p', 
  props: { 
    children: 'Login', 
    id: 'login-btn' 
  } 
}

React Element und React Component im Detail

<p id=&#39;login-btn&#39;>Login</p>
In diesem Artikel stellen wir React Element am Anfang vor, anstatt React Component wie auf der offiziellen Website oder den Lernmaterialien vorzustellen Das Verständnis von React Component ist natürlich.

Während der eigentlichen Entwicklung verwenden wir React.createElement nicht direkt. Es ist einfach zu langweilig, jede Komponente so zu schreiben. Zu diesem Zeitpunkt erschien React Component, also React Component.

Eine Komponente ist eine Funktion oder eine Klasse, die optional Eingaben akzeptiert und ein React-Element zurückgibt.

Ja, eine Komponente ist eine Funktion oder eine Klasse (natürlich Klasse). ist auch eine Funktion), die Eingabeparameter entgegennimmt und schließlich ein React-Element zurückgibt, ohne dass wir langweilige React-Elemente direkt schreiben müssen.

Wir verwenden also tatsächlich React Component, um React Element zu generieren, was das Entwicklungserlebnis zweifellos erheblich verbessern wird.

这里剖出一个思考题:所有 React Component 都需要返回  React Element 吗?显然是不需要的,那么 return null; 的 React 组件有存在的意义吗,它能完成并实现哪些巧妙的设计和思想?(请关注作者,下篇文章将会专门进行分析、讲解)

从场景实例来看问题

接下来,请看这样一段代码:

function Button ({ onLogin }) { 
  return React.createElement( 
    &#39;p&#39;, 
    {id: &#39;login-btn&#39;, onClick: onLogin}, 
    &#39;Login&#39; 
  )
}

我们定义了一个 Button 组件,它接收 onLogin 参数,并返回一个 React Element。注意 onLogin 参数是一个函数,并最终像 id:'login-btn' 一样成为了这个 React Element 的属性。

直到目前,我们见到了一个 React Element type 为 HTML 标签(“span”, “p”, etc)的情况。事实上,我们也可以传递另一个 React Element :

const element = React.createElement(
  User, 
  {name: &#39;Lucas&#39;},
  null 
)

注意此时 React.createElement 第一个参数是另一个 React Element,这与 type 值为 HTML 标签的情况不尽相同,当 React 发现 type 值为一个 class 或者函数时,它就会先看这个 class 或函数会返回什么样的 Element,并为这个 Element 设置正确的属性。

React 会一直不断重复这个过程(有点类似递归),直到没有 “createElement 调用 type 值为 class 或者 function” 的情况。

我们结合代码再来体会一下:

function Button ({ addFriend }) {
  return React.createElement(
    "button", 
    { onClick: addFriend }, 
    "Add Friend" 
  ) 
} 
function User({ name, addFriend }) { 
  return React.createElement(
    "p", 
    null,
    React.createElement( "p", null, name ),
    React.createElement(Button, { addFriend })
  ) 
}

上面有两个组件:Button 和 User,User 描述的 Dom 是一个 p 标签,这个 p 内,又存在一个 p 标签,这个 p 标签展示了用户的 name;还存在一个 Button。

现在我们来看 User 和 Button 中,React.createElement 返回情况:

function Button ({ addFriend }) { 
  return { 
    type: &#39;button&#39;, 
    props: { 
      onClick: addFriend, 
      children: &#39;Add Friend&#39; 
    } 
  } 
} 
function User ({ name, addFriend }) { 
  return { 
    type: &#39;p&#39;, 
    props: { 
      children: [{ 
        type: &#39;p&#39;,
        props: { children: name } 
      }, 
      { 
       type: Button, 
       props: { addFriend } 
      }]
    }
  }
}

你会发现,上面的输出中,我们发现了四种 type 值:

  • "button";

  • "p";

  • "p";

  • Button

当 React 发现 type 是 Button 时,它会查询这个 Button 组件会返回什么样的 React Element,并赋予正确的 props。

直到最终,React 会得到完整的表述 Dom 树的对象。在我们的例子中,就是:

<p style="margin-bottom: 7px;">{<br/>  type: &#39;p&#39;, <br/>  props: {<br/>    children: [{<br/>      type: &#39;p&#39;,<br/>      props: { children: &#39;Tyler McGinnis&#39; }<br/>    }, <br/>    { <br/>      type: &#39;button&#39;, <br/>      props: { <br/>        onClick: addFriend, <br/>        children: &#39;Add Friend&#39;<br/>      }<br/>     }]<br/>   } <br/>}<br/></p>

React 处理这些逻辑的过程就叫做 reconciliation,那么“这个过程(reconciliation)在何时被触发呢?”

答案当然就是每次 setState 或 ReactDOM.render 调用时。以后的分析文章将会更加详细的说明。

好吧,再回到 Tyler McGinnis 那个风骚的问题上。

Erkundung der internen Mechanismen von React

此时我们具备回答这个问题的一切知识了吗?稍等等,我要引出 JSX 这个老朋友了。

JSX 的角色

在 React Component 编写时,相信大家都在使用 JSX 来描述虚拟 Dom。当然,反过来说,React 其实也可以脱离 JSX 而存在。

文章开头部分,我提到 “不常被我们提起的 JSX 抽象层是如何联通 React 的?” 答案很简单,因为 JSX 总是被编译成为 React.createElement 而被调用。一般 Babel 为我们做了 JSX —> React.createElement 这件事情。

再看来先例:

function Button ({ addFriend }) {
  return React.createElement(
    "button",
    { onClick: addFriend },
    "Add Friend" 
   )
} 
function User({ name, addFriend }) { 
  return React.createElement(
    "p",
    null,
    React.createElement( "p", null, name),
    React.createElement(Button, { addFriend })
  )
}

对应我们总在写的 JSX 用法:

function Button ({ addFriend }) { 
  return ( 
    <button onClick={addFriend}>Add Friend</button> 
  )
}
function User ({ name, addFriend }) {
  return ( 
    <p>
     <p>{name}</p>
     <Button addFriend={addFriend}/>
    </p>
  )
}

就是一个编译产出的差别。

最终答案和文末彩蛋

那么,请你来回答“Icon 组件单独出现代表了什么?”

Icon 在 JSX 被编译之后,就有:

React.createElement(Icon, null)

你问我怎么知道这些编译结果的?

或者

你想知道你编写的 JSX 最终编译成了什么样子?

我写了一个小工具,进行对 JSX 的实时编译,放在 Github仓库中,它使用起来是这样子的:

平台一分为二,左边可以写 JSX,右边实时展现其编译结果:

Erkundung der internen Mechanismen von React

以及:

Erkundung der internen Mechanismen von React

这个工具最核心的代码其实就是使用 babel 进行编译:

let code = e.target.value;
try {
    this.setState({
        output: window.Babel.transform(code, {presets: [&#39;es2015&#39;, &#39;react&#39;]})
        .code,
        err: &#39;&#39;
    })
}
catch(err) {
    this.setState({err: err.message})
}

感兴趣的读者可以去 GitHub 仓库参看源码。

总结

其实不管是 JSX 还是 React Element、React Component 这些概念,都是大家在开发中天天接触到的。有的开发者也许能上手做项目,但是并没有深入理解其中的概念,更无法真正掌握 React 核心思想。

这些内容其实比较基础,但同时又很关键,对于后续理解 React/Preact 源码至关重要。在这个基础上,我会更新更多更加深入的类 React 实现原理剖析,感兴趣的读者可以关注。

我的其他几篇关于React技术栈的文章:

  • 通过实例,学习编写 React 组件的“最佳实践”

  • Binden Sie dies von React und schauen Sie sich die JS-Sprachentwicklung und das Framework-Design an

  • Die Erstellung der mobilen Webversion von Uber reicht nicht aus, um die ultimative Leistung zu erzielen Können wir dann die wahre Geschichte sehen?

  • Analysieren Sie die Twitter-Frontend-Architektur, um komplexes Szenendatendesign zu lernen

  • React Conf 2017 Zusammenfassung 1: Reagieren + ES next = ♥

  • React+Redux erstellt eine „NEWS EARLY“-Einzelseitenanwendung. Ein Projekt, um die Essenz des modernsten Technologie-Stacks zu verstehen.

  • Ein React+Redux-Projektbeispiel


Das obige ist der detaillierte Inhalt vonErkundung der internen Mechanismen von React. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn