React의 내부 메커니즘 탐색

一个新手
풀어 주다: 2017-10-25 15:06:31
원래의
1856명이 탐색했습니다.

React의 내부 메커니즘 탐색 - React 구성 요소 및 요소

이 문서는 비교적 기본이지만 React의 내부 메커니즘과 구현 원칙을 시작하는 데 중요합니다. 이미 잘 알고 계시다면:

React Component Render => JSX => React.createElement => Virtual Dom

프로세스를 건너뛰셔도 됩니다. .

Google 엔지니어의 교묘한 질문

몇 달 전, Google의 프론트 엔드 개발 전문가인 Tyler McGinnis는 자신의 개인 트위터 계정에 이러한 트윗을 게시하여 React 구성 요소에 대한 토론을 촉발시켰습니다.

React의 내부 메커니즘 탐색

그가 제기한 질문은 다음과 같습니다. 위 코드와 마찬가지로 React 컴포넌트 아이콘이 코드에 직접 나타나는데, 정확히 무엇을 의미하나요?

제공되는 옵션은 다음과 같습니다.

  • A. 구성 요소 선언

  • B. 구성 요소 인스턴스화

  • D.

  • 흥미롭게도, 응답한 개발자 중:

15%는 옵션 A를 선택했고

  • 8%는 옵션 B를 선택했습니다.

  • 항목 C는 45%는 항목 D를 선택했습니다.

  • React 개발 경험이 있는 프론트엔드 엔지니어라면 이 질문은 실제로 이해하기 쉽습니다. 핵심은 다음과 같습니다.

    React 요소, React 구성 요소 및 JSX 추상화 계층이 React를 연결하는 방법을 실제로 이해합니다.

    물론 React의 몇 가지 간단한 내부 작동 메커니즘도 이해해야 합니다.
  • 이 기사에서는 JSX 추상화 계층과

    React Reconciliation

    프로세스의 미스터리를 연구하게 됩니다.
React와 React Element는 정확히 무엇인가요?

처음으로 돌아가서 가장 독창적인 질문인 React란 정확히 무엇인지 생각해 봅시다.

간단히 말하면

React는 사용자 인터페이스를 구축하기 위한 라이브러리입니다.

React는 뷰 레이어(프레임워크...무엇이든...)를 구축하기 위한 클래스 라이브러리입니다. React 자체가 아무리 복잡하고 생태계가 아무리 거대하더라도

Building Views

는 항상 핵심입니다. 이 정보를 염두에 두고 오늘의 첫 번째 개념인

React Element

로 넘어가려고 합니다.

간단히 말해서 React Element는 화면에 "당신이 원하는 것"이 ​​무엇인지 설명합니다.

추상적으로 말하면 React Element 요소는 Dom Node를 설명하는 객체입니다.

React Element는 화면에 표시되는 실제 요소가 아니기 때문에 "description"이라는 문구를 참고하세요. 오히려 그것은 실제 사물에 대한 설명의 모음입니다. 존재하는 것이 합리적입니다. React Element의 존재 의미와 그러한 개념이 있는 이유를 살펴보겠습니다.

JavaScript 객체는 매우 가볍습니다. 객체를 React 요소로 사용하면 React는 운영 비용에 대해 크게 걱정하지 않고도 이러한 요소를 쉽게 생성하거나 삭제할 수 있습니다.

React에는 이러한 객체를 분석하는 기능이 있으며 더 나아가 가상 Dom을 분석하는 기능도 있습니다. 변경 사항이 발생할 때 가상 Dom(실제 Dom과 비교하여)을 업데이트하면 성능상의 이점이 상당합니다.

  • Dom 노드를 설명하는 객체(또는 React Element)를 생성하기 위해 React.createElement 메서드를 사용할 수 있습니다.

    const element = React.createElement( 
      'p', 
      {id: 'login-btn'}, 
      'Login'
    )
    로그인 후 복사

    여기에서 React.createElement 메서드는 세 가지 매개 변수를 허용합니다.
  • 문자열을 나타냅니다. 태그 이름(p,span 등)

위에서 React.createElement 메소드가 호출된 후 자바스크립트 객체가 반환됩니다:

{ 
  type: 'p', 
  props: { 
    children: 'Login', 
    id: 'login-btn' 
  } 
}
로그인 후 복사

그런 다음 ReactDOM.render 메소드를 사용하여 실제 DOM으로 렌더링하면 다음을 얻게 됩니다:
    <p id=&#39;login-btn&#39;>Login</p>
    로그인 후 복사
  • 그리고 이것은 다음과 같습니다. 실제 Dom 노드입니다.

    지금까지는 이해하기 어려운 개념이 없습니다.
  • React Element와 React Component 심층 탐구

    이번 글에서는 공식 홈페이지나 학습자료처럼 React Component를 소개하는 것이 아니라, 처음에 React Element를 소개했습니다.
  • 실제 개발에서는 React.createElement를 직접 사용하지 않습니다. 그렇게 하기에는 너무 지루합니다. 모든 구성요소를 이렇게 작성하면 확실히 엉망이 될 것입니다. 이때 React Component, 즉 React Component가 등장했습니다.

  • 구성 요소는 선택적으로 입력을 받아들이고 React 요소를 반환하는 함수 또는 클래스입니다.

예, 구성 요소는 함수 또는 클래스입니다(물론 클래스도 함수입니다). 입력 매개 변수를 사용하고 마지막으로 지루한 React Element를 직접 작성하도록 요구하는 대신 React Element를 반환합니다.

그래서 우리는 실제로 React Component를 사용하여 React Element를 생성하는데, 이는 의심할 여지 없이 개발 경험을 크게 향상시킬 것입니다.

这里剖出一个思考题:所有 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 那个风骚的问题上。

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,右边实时展现其编译结果:

React의 내부 메커니즘 탐색

以及:

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 组件的“最佳实践”

  • 이것을 React에서 바인딩하고 JS 언어 개발 및 프레임워크 디자인을 살펴보세요

  • Uber 모바일 웹 버전을 구축하는 것만으로는 최고의 성능을 달성할 수 없습니다

  • Twitter 프런트엔드 아키텍처를 분석하여 복잡한 장면 데이터 디자인 학습

  • React Conf 2017 요약 1: React + ES next = ♥

  • React+Redux를 통해 "NEWS EARLY" 단일 페이지 애플리케이션 만들기 최첨단 기술 스택의 본질을 이해하기 위한 프로젝트

  • react+redux 프로젝트 예시


위 내용은 React의 내부 메커니즘 탐색의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!