React 组件和 React 元素的区别

IT技术 javascript reactjs
2021-04-20 07:42:35

React Component 和 React Element 有什么区别?文档提到了两者但没有详细说明,一些方法需要组件,其他元素......

6个回答

这里涉及三种相关的事物,它们都有自己的名字:

  • 组件
  • 组件实例
  • 元素

这有点令人惊讶,因为如果您习惯于其他 UI 框架,您可能会认为只有两种东西,大致对应于类(如Widget)和实例(如new Widget())。在 React 中不是这样。组件实例与元素不是一回事,它们之间也没有一一对应的关系。为了说明这一点,请考虑以下代码:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    console.log('This is a component instance:', this);
  }

  render() {
    const another_element = <div>Hello, World!</div>;
    console.log('This is also an element:', another_element);
    return another_element;
  }
}

console.log('This is a component:', MyComponent)

const element = <MyComponent/>;

console.log('This is an element:', element);

ReactDOM.render(
  element,
  document.getElementById('root')
);

在上面的代码中:

  • MyComponent类本身)是一个组件
  • element是一个元素。不是一个实例MyComponent; 相反,它只是对要创建的组件实例的描述。这是一个对象keypropsreftype属性。在这里,key并且refnullprops是一个空的对象,typeMyComponent
  • 一个实例MyComponent被创建(并且,在上述例子中,从它的构造记录本身)时element被呈现。
  • another_element也是一个元素,并有keyrefpropstype刚才一样的属性element那样-但这次的值type是字符串"div"

React 团队的博客文章React Components、Elements 和 Instances中详细探讨了 React 具有这三个不同概念的设计原因,我推荐阅读。

最后,应该注意的是,虽然官方文档严格使用术语“组件”来指代函数或类,使用“组件实例”来指代实例,但其他来源不一定遵循此术语;在 GitHub 上阅读 Stack Overflow 答案或讨论时,您应该会看到“组件”使用(错误地)表示“组件实例”。

总而言之,Component 可用于创建一个 Instance,当该 Instance 被渲染时,就会创建一个 Element。
2021-06-02 07:42:35
@Andy ...而且,虽然它可能不太常见,但多个组件也可以由同一元素描述 - 甚至同时。您可以将一个元素存储在一个变量中——比如说el = <SomeComponent>——然后将该元素多次嵌入到某个render()方法(即 do <div>{el}{el}{el}{el}</div>返回的某个大型 JSX 表达式中
2021-06-02 07:42:35
对 React Node 有什么想法吗?
2021-06-05 07:42:35
这怎么不是组件实例和元素之间的一对一关系?您是否建议一个元素可以描述多个组件实例?或者多个元素可以描述同一个组件实例?否则,它们根据定义是一对一相关的。
2021-06-07 07:42:35
@Andy 多个元素可以描述同一个组件实例。(不是同时发生,而是在该实例的整个生命周期中。如果您有一个始终<Child/>从其render()方法返回的父组件,则每次render()调用它都会返回一个新元素,但Child可以重用已经存在的组件来实现这一点元素。)
2021-06-17 07:42:35

为了进一步详细说明答案,React Element 没有任何方法,原型上也没有任何内容。这也使他们快速。

“ReactElement 是 DOM 元素的轻量级、无状态、不可变的虚拟表示”——React术语表

react组件render()函数在幕后返回react元素的 DOM 树(顺便说一下,这是虚拟 DOM)。涉及到一些复杂的映射和差异逻辑,但基本上这些 React 元素映射到 DOM 元素。

你也可以直接创建一个 Element ,React.createElement(arg)其中 arg 可以是一个 html 标签名称,或者一个 React Component 类。

这个答案来自很久以前(2015 年),VDOM 结构及其访问会发生变化。我想我必须更新它,但从那时起我就没有使用过 React,所以我必须先进行研究。如果有人想对此进行审核或发表评论,我会很高兴!:)
2021-05-23 07:42:35
我不确定这ReactElement是 VDOM 本身……但我不是这个主题的专家,这只是一种预感。根据我的理解,Element仍然需要将反应渲染到 VDOM,然后将其与“以前的”VDOM 进行区分。我认为user6445533's answer说同样的。对 ?我不是专家,但不知何故,常识告诉我,经过一番思考,这是唯一有意义的解释……但我的直觉可能是错误的。
2021-06-08 07:42:35

react元素

React Element 只是一个Object没有自己方法的普通 JavaScript 它基本上有四个属性:

  • type,String表示 HTML 标签或引用 React 组件的引用
  • key, aString唯一标识一个 React 元素
  • ref,访问底层 DOM 节点或 React 组件实例的引用)
  • props(属性Object

React Element 不是 React 组件的实例。它只是type对要创建的 React 组件实例(或取决于HTML 标签)应该是什么样子的简化“描述”

描述 React 组件的 React Element 不知道它最终被渲染到哪个 DOM 节点——这个关联是抽象的,将在渲染时解析。

React Elements 可能包含子元素,因此能够形成代表虚拟 DOM 树的元素树。

React 组件和 React 组件实例

自定义 React 组件要么是React.createClass通过扩展React.Component(ES2015)创建的,要么是通过扩展创建的如果一个 React 组件被实例化,它需要一个props Object并返回一个实例,它被称为一个 React 组件实例。

React 组件可以包含状态并可以访问 React Lifecycle 方法。它必须至少有一个render方法,该方法在调用时返回一个 React Element(-tree)。请注意,您永远不会自己构建 React 组件实例,而是让 React 为您创建它。

这和马克的回答是“好”的……他们澄清了 React Element 不是 VDOM 的观点!:) :) ... 这是一种“提升”——有点像编程语言的抽象语法树。或者一个 Monad。简而言之。
2021-05-23 07:42:35

React 元素与 React 组件

react元素

  • React Element 是从组件返回的内容。它是一个虚拟地描述组件所代表的 DOM 节点的对象。
  • 对于函数组件,此元素是函数返回的对象。
  • 对于类组件,元素是组件的渲染函数返回的对象。电阻
  • React 元素不是我们在浏览器中看到的。它们只是内存中的对象,我们无法更改它们的任何内容。
  • React 元素可以具有type除原生 HTML 元素之外的其他属性。
我们知道以下几点:
  • react 元素描述了我们希望在屏幕上看到的内容。
更复杂的说法是:
  • React 元素是 DOM 节点的对象表示。

_在这里进行区分很重要,因为元素不是我们在屏幕上看到的实际事物,而是对象表示是呈现的内容。

React 在这些方面做得很好:

  • React 可以在没有太多开销的情况下创建和销毁这些元素。JS 对象是轻量级和低成本的。
  • React 可以将一个对象与之前的对象表示进行比较,以查看发生了什么变化。
  • React 可以更新实际的 DOM,特别是它检测到的变化发生的地方。这有一些性能优势。
我们可以使用该createElement方法创建 DOM 节点(又名 React 元素)的对象表示
const element = React.createElement(
  'div',
  {id: 'login-btn'},
  'Login'
  )
这里createElement接受三个参数
  1. 标签名称(例如 div、span 等)
  2. 我们希望元素具有的任何属性
  3. 元素的子元素的内容(例如读取的文本Login
createElement调用返回一个对象
{
  type: 'div',
  props: {
    children: 'Login',
    id: 'login-btn'
  }
}
当它被渲染到 DOM(使用ReactDOM.render)时,我们将有一个新的 DOM 节点,如下所示:
<div id='login-btn'>Login</div>

哈扎!

胡扎

通常,React 是从组件优先的方法中教授的,但是理解元素优先可以平滑地过渡到组件。

react组件

组件是一个函数或一个类,它可以选择接受输入并返回一个 React 元素。

  • React 组件是一个模板。一个蓝图。一个全局定义。这可以是函数或类(带有渲染函数)。

  • 如果 react 将类或函数视为第一个参数,它会检查它渲染的元素,给定相应的 props 并继续这样做,直到不再createElement有将类或函数作为第一个参数的调用.

  • 当 React 看到一个具有函数或类类型的元素时,它会咨询该组件以了解它应该返回哪个元素,给定相应的 props。

  • 在此过程结束时,React 将拥有 DOM 树的完整对象表示。这整个过程在 React 中称为 reconciliation,每次触发setStateReactDOM.render调用。

基于类的组件

类语法是定义 React 组件的最常见方式之一。虽然比函数式语法更冗长,但它以生命周期钩子的形式提供更多控制。

  • 我们可以渲染同一组件的多个实例。
  • 实例是在基于类的组件中使用的“this”关键字。
  • 不是手动创建的,而是在 React 内存中的某个地方。

创建类组件

// MyComponent.js
import React, { Component } from 'react';

class MyComponent extends Component {
  render() {
    return (
      <div>This is my component.</div>
    );
  }
}

export default MyComponent;

在任何其他组件中使用它

// MyOtherComponent.js
import React, { Component } from 'react';
import MyComponent from './MyComponent';

class MyOtherComponent extends Component {
  render() {
    return (
      <div>
        <div>This is my other component.</div>
        <MyComponent />
      </div>
    );
  }
}

export default MyOtherComponent;

使用props

<MyComponent myProp="This is passed as a prop." />

props可以通过 this.props

class MyComponent extends Component {
  render() {
    const {myProp} = this.props;
    return (
      <div>{myProp}</div>
    );
  }
}

使用状态

class MyComponent extends Component {
  render() {
    const {myState} = this.state || {};
    const message = `The current state is ${myState}.`;
    return (
      <div>{message}</div>
    );
  }
}

使用生命周期钩子

class MyComponent extends Component {
  // Executes after the component is rendered for the first time
  componentDidMount() {
    this.setState({myState: 'Florida'});
  }

  render() {
    const {myState} = this.state || {};
    const message = `The current state is ${myState}.`;
    return (
      <div>{message}</div>
    );
  }
}
基于函数的组件
  • 没有实例。
  • 可以多次渲染,但 React 不会将本地实例与每个渲染相关联。
  • React 使用函数的调用来确定要为函数呈现什么 DOM 元素。

createElement

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

function User({ name, addFriend }) {
  return React.createElement(
    "div",
    null,
    React.createElement(
      "p",
      null,
      name
    ),
    React.createElement(Button, { addFriend })
  )
}

用什么createElement回报

function Button ({ addFriend }) {
  return {
    type: 'button',
    props: {
      onClick: addFriend,
      children: 'Add Friend'
    }
  }
}

function User ({ name, addFriend }) {
  return {
    type: 'div',
    props: {
      children: [
        {
          type: 'p',
          props: {
            children: name
          }
        },
        {
          type: Button,
          props: {
            addFriend
          }
        }
      ]
    }
  }
}

这里我们有一个Button组件,它接受一个onLogin输入并返回一个 React 元素。

  • Button组件接收一个onLogin方法作为其属性。
  • 为了将它传递给我们的 DOM 对象表示,我们将它作为第二个参数传递给 createElement,就像我们对id属性所做的一样
哇。你的回答很棒。
2021-05-27 07:42:35

React Element- 它是一个简单的对象,它描述了一个 DOM 节点及其属性或属性。它是一个不可变的描述对象,您不能对其应用任何方法。

例如——

<button class="blue"></button>

React Component- 它是一个接受输入并返回 React 元素的函数或类。它必须保持对 DOM 节点和子组件实例的引用。

const SignIn = () => (
  <div>
   <p>Sign In</p>
   <button>Continue</button>
   <button color='blue'>Cancel</button>
  </div>
);