목차
구성요소는 함수입니다
props 和 state 的实现
먼저 컴포넌트 외부의 props를 컴포넌트에 전달하고 render 함수에서 다음 코드를 수정합니다.
웹 프론트엔드 JS 튜토리얼 React 구성요소 및 상태|소품 구문 분석

React 구성요소 및 상태|소품 구문 분석

Jul 13, 2018 pm 03:10 PM
react.js

소스 코드를 읽을 때의 문제점 중 하나는 백본을 바로잡지 못하는 딜레마에 빠지게 된다는 것입니다. 이 기사 시리즈는 React 프레임워크(JSX/virtual DOM/Components/.. .) (x)react를 구현하는 동안

구성요소는 함수입니다

이전 글에서 JSX와 Virtual DOM을 인터페이스에 렌더링하는 과정을 설명하고 해당 코드를 구현했습니다.

import React from 'react'
import ReactDOM from 'react-dom'

const element = (
  <p>
    hello<span>world!</span>
  </p>
)

ReactDOM.render(
  element,
  document.getElementById('root')
)
로그인 후 복사

이 섹션에서는 구성 요소가 인터페이스 프로세스에 렌더링되는 방법을 계속해서 살펴보겠습니다. 여기서는 컴포넌트의 개념을 소개합니다. 컴포넌트는 본질적으로 함수입니다. 다음은 표준 컴포넌트 코드입니다: 组件本质上就是一个函数,如下就是一段标准组件代码:

import React from 'react'

// 写法 1:
class A {
  render() {
    return <p>I'm componentA</p>
  }
}

// 写法 2:无状态组件
const A = () =&gt; <p>I'm componentA</p>

ReactDOM.render(<a></a>, document.body)
로그인 후 복사

<a name="componentA"></a> 是 JSX 的写法,和上一篇同理,babel 将其转化为 React.createElement() 的形式,转化结果如下所示:

React.createElement(A, null)
로그인 후 복사

可以看到当 JSX 中是自定义组件的时候,createElement 后接的第一个参数变为了函数,在 repl 打印 <a name="componentA"></a>,结果如下:

{
  attributes: undefined,
  children: [],
  key: undefined,
  nodeName: ƒ A()
}
로그인 후 복사

注意这时返回的 Virtual DOM 中的 nodeName 也变为了函数。根据这些线索,我们对之前的 render 函数进行改造。

function render(vdom, container) {
  if (_.isFunction(vdom.nodeName)) { // 如果 JSX 中是自定义组件
    let component, returnVdom
    if (vdom.nodeName.prototype.render) {
      component = new vdom.nodeName()
      returnVdom = component.render()
    } else {
      returnVdom = vdom.nodeName() // 针对无状态组件:const A = () =&gt; <p>I'm componentsA</p>
    }
    render(returnVdom, container)
    return
  }
}
로그인 후 복사

至此,我们完成了对组件的处理逻辑。

props 和 state 的实现

在上个小节组件 A 中,是没有引入任何属性和状态的,我们希望组件间能进行属性的传递(props)以及组件内能进行状态的记录(state)。

import React, { Component } from 'react'

class A extends Component {
  render() {
    return <p>I'm {this.props.name}</p>
  }
}

ReactDOM.render(<a></a>, document.body)
로그인 후 복사

在上面这段代码中,看到 A 函数继承自 Component。我们来构造这个父类 Component,并在其添加 state、props、setState 等属性方法,从而让子类继承到它们。

function Component(props) {
  this.props = props
  this.state = this.state || {}
}
로그인 후 복사

首先,我们将组件外的 props 传进组件内,修改 render 函数中以下代码:

function render(vdom, container) {
  if (_.isFunction(vdom.nodeName)) {
    let component, returnVdom
    if (vdom.nodeName.prototype.render) {
      component = new vdom.nodeName(vdom.attributes) // 将组件外的 props 传进组件内
      returnVdom = component.render()
    } else {
      returnVdom = vdom.nodeName(vdom.attributes)     // 处理无状态组件:const A = (props) =&gt; <p>I'm {props.name}</p>
    }
    ...
  }
  ...
}
로그인 후 복사

实现完组件间 props 的传递后,再来聊聊 state,在 react 中是通过 setState 来完成组件状态的改变的,后续章节会对这个 api(异步)深入探究,这里简单实现如下:

function Component(props) {
  this.props = props
  this.state = this.state || {}
}

Component.prototype.setState = function() {
  this.state = Object.assign({}, this.state, updateObj) // 这里简单实现,后续篇章会深入探究
  const returnVdom = this.render() // 重新渲染
  document.getElementById('root').innerHTML = null
  render(returnVdom, document.getElementById('root'))
}
로그인 후 복사

此时虽然已经实现了 setState 的功能,但是 document.getElementById('root')

Component.prototype.setState = function(updateObj) {
  this.state = Object.assign({}, this.state, updateObj)
  _render(this) // 重新渲染
}
로그인 후 복사
<a name="comComponentA"></a> JSX로 작성했는데, 이전 글과 마찬가지로 babel을 React.createElement() 형태로 변환해 보면 다음과 같습니다.

function render(vdom, container) {
  let component
  if (_.isFunction(vdom.nodeName)) {
    if (vdom.nodeName.prototype.render) {
      component = new vdom.nodeName(vdom.attributes)
    } else {
      component = vdom.nodeName(vdom.attributes) // 处理无状态组件:const A = (props) =&gt; <p>I'm {props.name}</p>
    }
  }
  component ? _render(component, container) : _render(vdom, container)
}
로그인 후 복사
Custom Component가 있으면 알 수 있습니다. JSX, createElement 다음에 첫 번째 매개변수가 함수가 되어 repl에 <a name="comComponentA"></a>를 인쇄하면 결과는 다음과 같습니다.

function _render(component, container) {
  const vdom = component.render ? component.render() : component
  if (_.isString(vdom) || _.isNumber(vdom)) {
    container.innerText = container.innerText + vdom
    return
  }
  const dom = document.createElement(vdom.nodeName)
  for (let attr in vdom.attributes) {
    setAttribute(dom, attr, vdom.attributes[attr])
  }
  vdom.children.forEach(vdomChild =&gt; render(vdomChild, dom))
  if (component.container) {  // 注意:调用 setState 方法时是进入这段逻辑,从而实现我们将 dom 的逻辑与 setState 函数分离的目标;知识点: new 出来的同一个实例
    component.container.innerHTML = null
    component.container.appendChild(dom)
    return
  }
  component.container = container
  container.appendChild(dom)
}
로그인 후 복사
반환된 Virtual DOM도 작동하도록 변경되었습니다. 이러한 단서를 바탕으로 이전 render 기능을 변형했습니다.

class A extends Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 1
    }
  }

  click() {
    this.setState({
      count: ++this.state.count
    })
  }

  render() {
    return (
      <p>
        <button>Click Me!</button>
        </p><p>{this.props.name}:{this.state.count}</p>
      
    )
  }
}

ReactDOM.render(
  <a></a>,
  document.getElementById('root')
)
로그인 후 복사
이 시점에서 컴포넌트의 처리 로직이 완료되었습니다.

props 및 state 구현

React 구성요소 및 상태|소품 구문 분석이전 섹션의 컴포넌트 A에는 속성과 상태가 도입되지 않았습니다. 컴포넌트(props) 간에 속성을 전달할 수 있고 컴포넌트(state) 내에 상태를 기록할 수 있기를 바랍니다.

rrreee

위 코드에서 A 함수는 Component에서 상속되는 것을 볼 수 있습니다. 이 상위 클래스 Component를 구성하고 여기에 state, props, setState 및 기타 속성 메서드를 추가하여 하위 클래스가 상속할 수 있도록 하겠습니다.

rrreee

먼저 컴포넌트 외부의 props를 컴포넌트에 전달하고 render 함수에서 다음 코드를 수정합니다.

rrreee

컴포넌트 간 props 전송이 완료된 후, 반응에서는 setState를 사용합니다. 구성 요소 상태를 완료합니다. 다음 장에서는 이 API(비동기)를 자세히 살펴보겠습니다. 여기서 간단한 구현은 다음과 같습니다.

rrreee

setState 함수가 현재 구현되었지만 document.getElementById('root' ) 이는 분명히 우리가 setState에 노드를 작성하려는 것이 아닙니다. _render 함수와 관련된 dom 노드를 전송합니다.

rrreee

당연히 이와 관련된 렌더 함수를 재구성합니다.

rrreee

에서 _render를 분리합니다. render 함수 이 함수의 목적은 _render 논리가 setState 함수에서 호출되도록 허용하는 것입니다. 완전한 _render 함수는 다음과 같습니다:

rrreee

다음 사용 사례를 사용하여 작성된 반응을 실행해 보겠습니다! rrreee렌더링은 다음과 같습니다.

🎜Summary🎜🎜Components는 함수입니다. JSX가 사용자 정의 구성 요소인 경우 babel 변환 후 React.createElement(fn, ..)의 첫 번째 매개 변수는 함수가 됩니다. 🎜🎜또한 state/props/setState와 같은 API를 상위 클래스 React.Component에 캡슐화하여 이러한 속성과 메서드를 하위 클래스에서 호출할 수 있습니다. 🎜🎜위 내용은 이 글의 전체 내용입니다. 모든 분들의 학습에 도움이 되었으면 좋겠습니다. 더 많은 관련 내용은 PHP 중국어 홈페이지를 주목해주세요! 🎜🎜관련 권장 사항: 🎜🎜🎜vue의 config/index.js에 대한 자세한 설명: 구성🎜🎜🎜🎜Angular 템플릿 구문 설명🎜🎜🎜

위 내용은 React 구성요소 및 상태|소품 구문 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

뜨거운 기사 태그

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

React 상위 컴포넌트에서 하위 컴포넌트의 메소드를 호출하는 방법 React 상위 컴포넌트에서 하위 컴포넌트의 메소드를 호출하는 방법 Dec 27, 2022 pm 07:01 PM

React 상위 컴포넌트에서 하위 컴포넌트의 메소드를 호출하는 방법

React 소스 코드를 디버깅하는 방법은 무엇입니까? 여러 도구를 사용한 디버깅 방법 소개 React 소스 코드를 디버깅하는 방법은 무엇입니까? 여러 도구를 사용한 디버깅 방법 소개 Mar 31, 2023 pm 06:54 PM

React 소스 코드를 디버깅하는 방법은 무엇입니까? 여러 도구를 사용한 디버깅 방법 소개

React의 커스텀 Hook에 대한 심층적인 이해 React의 커스텀 Hook에 대한 심층적인 이해 Apr 20, 2023 pm 06:22 PM

React의 커스텀 Hook에 대한 심층적인 이해

React가 앱 구축을 위한 첫 번째 선택으로 Vite를 사용하지 않는 이유 React가 앱 구축을 위한 첫 번째 선택으로 Vite를 사용하지 않는 이유 Feb 03, 2023 pm 06:41 PM

React가 앱 구축을 위한 첫 번째 선택으로 Vite를 사용하지 않는 이유

7가지 훌륭하고 실용적인 React 구성 요소 라이브러리(압박 속에서 공유됨) 7가지 훌륭하고 실용적인 React 구성 요소 라이브러리(압박 속에서 공유됨) Nov 04, 2022 pm 08:00 PM

7가지 훌륭하고 실용적인 React 구성 요소 라이브러리(압박 속에서 공유됨)

반응에서 div 높이를 설정하는 방법 반응에서 div 높이를 설정하는 방법 Jan 06, 2023 am 10:19 AM

반응에서 div 높이를 설정하는 방법

[번역] 커스텀 후크를 사용하여 React 구성요소 리팩토링 [번역] 커스텀 후크를 사용하여 React 구성요소 리팩토링 Jan 17, 2023 pm 08:13 PM

[번역] 커스텀 후크를 사용하여 React 구성요소 리팩토링

Vuex와 Pinia의 디자인과 구현의 차이점에 대해 이야기해 보겠습니다. Vuex와 Pinia의 디자인과 구현의 차이점에 대해 이야기해 보겠습니다. Dec 07, 2022 pm 06:24 PM

Vuex와 Pinia의 디자인과 구현의 차이점에 대해 이야기해 보겠습니다.

See all articles