目次
コンポーネントは関数です
props 和 state 的实现
rrreee
ホームページ ウェブフロントエンド jsチュートリアル React コンポーネントと state|props の解析

React コンポーネントと state|props の解析

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

ソース コードを読む際の難点の 1 つは、バックボーンを整理しないというジレンマに陥ることです。このシリーズの記事では、React フレームワーク (JSX/仮想 DOM/コンポーネント/...) のバックボーン コンテンツを整理します。 ) (x)react.を実装しながら

コンポーネントは関数です

前の記事 JSX と仮想 DOM では、インターフェースへの JSX レンダリングのプロセスを説明し、対応するコードを実装しました。コード呼び出しは次のとおりです。

このセクションでは、コンポーネントがインターフェイス プロセスにどのようにレンダリングされるかを引き続き調査していきます。ここでは、コンポーネントの概念を紹介します。コンポーネントは本質的に関数です。以下は標準コンポーネント コードです:

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')<a name="componentA"></a> > 前回の記事と同様に、babel で React.createElement() の形式に変換すると以下のようになります。 JSX、createElement の後に最初のパラメータが関数になり、repl で <a name="componentA"></a> を出力すると、結果は次のようになります。

Component.prototype.setState = function(updateObj) {
  this.state = Object.assign({}, this.state, updateObj)
  _render(this) // 重新渲染
}
ログイン後にコピー

返された仮想 DOM も機能するように変更されました。これらの手がかりに基づいて、前の render 関数を変換しました。

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)
}
ログイン後にコピー

この時点で、コンポーネントの処理ロジックが完成しました。

プロパティと状態の実装

前のセクションのコンポーネント 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)
}
ログイン後にコピー

上記のコードでは、A 関数が Component から継承していることがわかります。この親クラス Component を構築し、それに state、props、setState、その他の属性メソッドを追加して、サブクラスがそれらを継承できるようにしましょう。 React コンポーネントと state|props の解析

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 を渡し、render 関数で次のコードを変更します。

rrreee

コンポーネント間での props の転送が完了したら、react では setState を使用して状態について説明します。コンポーネントの状態を完了します。変更については、後続の章でこの API (非同期) について詳しく説明します。ここでの簡単な実装は次のとおりです。

rrreee

この時点では setState 関数が実装されていますが、document.getElementById('root' ) setState にノードを書き込むのは明らかにそうではありません。_render 関数に関連する dom ノードを転送します:

rrreee

当然、それに関連する render 関数を再構築します:

rrreee

render 関数 この関数の目的は、setState 関数で _render ロジックを呼び出せるようにすることです。完全な _render 関数は次のとおりです:

rrreee

次のユースケースを使用して、書かれた React を実行してみましょう!

rrreee

レンダリングは次のとおりです:

コンポーネントは関数です。JSX がカスタムコンポーネントの場合、Babel 変換後の React.createElement(fn, ..) の最初のパラメーターは関数になります。また、他のロジックや HTML 要素についても同様です。 JSX; 🎜🎜 さらに、state/props/setState などの API を親クラス React.Component にカプセル化して、これらのプロパティとメソッドをサブクラスで呼び出すことができるようにしました。 🎜🎜上記がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。 🎜🎜関連する推奨事項: 🎜🎜🎜 vue の config/index.js の詳細な説明: 構成🎜🎜🎜🎜 Angular テンプレート構文の説明🎜🎜🎜

以上がReact コンポーネントと state|props の解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Reactの親コンポーネントで子コンポーネントのメソッドを呼び出す方法 Reactの親コンポーネントで子コンポーネントのメソッドを呼び出す方法 Dec 27, 2022 pm 07:01 PM

呼び出しメソッド: 1. クラス コンポーネントの呼び出しは、React.createRef()、ref または props のカスタム onRef 属性の関数宣言を使用して実装できます; 2. 関数コンポーネントおよびフック コンポーネントの呼び出しは、useImperativeHandle または forwardRef を使用して実装できます。子コンポーネントの ref が実装されています。

React ソースコードをデバッグするにはどうすればよいですか?複数のツールを使用したデバッグ方法の紹介 React ソースコードをデバッグするにはどうすればよいですか?複数のツールを使用したデバッグ方法の紹介 Mar 31, 2023 pm 06:54 PM

React ソースコードをデバッグするにはどうすればよいですか?次の記事では、さまざまなツールで React のソース コードをデバッグする方法について説明し、コントリビューター、create-react-app、vite プロジェクトで React の実際のソース コードをデバッグする方法を紹介します。

React のカスタムフックについての深い理解 React のカスタムフックについての深い理解 Apr 20, 2023 pm 06:22 PM

React カスタム フックは、コンポーネント ロジックを再利用可能な関数にカプセル化する方法であり、クラスを作成せずに状態ロジックを再利用する方法を提供します。この記事では、カプセル化フックをカスタマイズする方法を詳しく紹介します。

React がアプリ構築の第一選択肢として Vite を使用しない理由 React がアプリ構築の第一選択肢として Vite を使用しない理由 Feb 03, 2023 pm 06:41 PM

React はなぜ Vite をアプリケーション構築の第一の選択肢として使用しないのでしょうか?次の記事では、React が Vite をデフォルトの推奨事項として推奨しない理由について説明します。

Reactでdivの高さを設定する方法 Reactでdivの高さを設定する方法 Jan 06, 2023 am 10:19 AM

React で div の高さを設定する方法: 1. CSS を通じて div の高さを実装します; 2. ステートでオブジェクト C を宣言し、オブジェクトに変更ボタンのスタイルを格納し、A を取得して C の "marginTop" をリセットします. それがキャンです。

7 つの優れた実用的な React コンポーネント ライブラリ (プレッシャーの下で共有) 7 つの優れた実用的な React コンポーネント ライブラリ (プレッシャーの下で共有) Nov 04, 2022 pm 08:00 PM

この記事では、日常の開発で頻繁に使用される、優れた実用的な React コンポーネント ライブラリを 7 つ紹介します。

よりクリーンな React コードを書くための 10 の実践的なヒント よりクリーンな React コードを書くための 10 の実践的なヒント Jan 03, 2023 pm 08:18 PM

この記事では、よりシンプルな React コードを記述するための 10 の実践的なヒントを紹介します。

[翻訳] カスタムフックを使用した React コンポーネントのリファクタリング [翻訳] カスタムフックを使用した React コンポーネントのリファクタリング Jan 17, 2023 pm 08:13 PM

React の関数コンポーネントについて人々が話し、関数コンポーネントは必然的に大きくなり、論理的により複雑になるという話をよく聞きます。結局のところ、コンポーネントを「関数」で記述したため、コンポーネントが拡張され、関数も拡張し続けることを受け入れる必要があります。

See all articles