>  기사  >  웹 프론트엔드  >  React 구성요소 및 상태|소품 구문 분석

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

不言
不言원래의
2018-07-13 15:10:241454검색

소스 코드를 읽을 때의 문제점 중 하나는 백본을 바로잡지 못하는 딜레마에 빠지게 된다는 것입니다. 이 기사 시리즈는 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 = () => <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 = () => <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) => <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) => <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 => 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으로 문의하세요.