反应元件与反应元件的区别

反应元件和反应元件的区别是什么?文档提到了这两者,但没有详细说明,有些方法需要组件,其他元素..。

66111 次浏览

为了进一步阐述这个问题的答案,React Element 没有任何方法,也没有关于原型的任何东西。这也使他们更快。

“ ReactElement 是一个轻量级的、无状态的、不可变的 DOM 元素的实际代表”-反应术语词汇

A react component render() function returns a DOM tree of react elements behind the scenes (This is the virtual DOM btw). There is some complex mapping and diff logic involved, but basically these React elements map to the DOM elements.

您还可以直接创建 Element React.createElement(arg),其中 arg 可以是 html 标记名,也可以是 React Component 类。

反应元素

A React Element is just a plain old JavaScript Object without own methods. It has essentially four properties:

  • type,表示 HTML 标记或引用反应组件的 String
  • key,唯一标识反应元素的 String
  • ref, a reference to access either the underlying DOM node or React Component Instance)
  • props(属性 Object)

A React Element is not an instance of a React Component. It is just a simplified "description" of how the React Component Instance (or depending on the type an HTML tag) to be created should look like.

描述 React Component 的 React Element 不知道它最终呈现到哪个 DOM 节点-这种关联是抽象的,并且在呈现时将被解析。

React Elements 可能包含子元素,因此能够形成元素树,这表示 Virtual DOM 树。

反应组件和反应组件实例

定制的反应组件可以由 React.createClass创建,也可以通过扩展 React.Component(ES2015)创建。如果一个反应组件被实例化,它需要一个 propsObject并返回一个实例,这个实例被称为反应组件实例。

A React Component can contain state and has access to the React Lifecycle methods. It must have at least a render method, which returns a React Element(-tree) when invoked. Please note that you never construct React Component Instances yourself but let React create it for you.

React Element是您认为是基本 html (准确地说是 dom)元素的元素。它只是一种不使用极具争议的 jsx 格式来创建元素的方法。

React Component是可以作为对象考虑的。它有自己的方法,支持 React lifecycles,并且通常是不可重用的(至少还没有发现任何重用,欢迎参考示例)。它必须有一个渲染函数。

React Class就是所谓的类。功能方面的 React ClassReact Component是相同的。只有语法才是真正的变化,因为 React Component是基于 ES6 syntax的。另一个主要变化是不再支持函数的默认绑定,除非使用箭头函数。从 ES6开始,也不再支持 Mixins

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>
);

这里涉及到 相关的东西,有他们自己的名字:

  • 零件
  • 组件实例
  • 元素

This is slightly surprising, since if you're used to other UI frameworks you might expect that there'd only be two kinds of thing, roughly corresponding to classes (like Widget) and instances (like new Widget()). That's not the case in React; component instances are 没有 the same thing as elements, nor is there a one-to-one relationship between them. To illustrate this, consider this code:

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的一个实例 MyComponent2; 相反,它只是要创建的组件实例的描述。它是一个具有 keypropsreftype属性的对象。在这里,keyrefnullprops是一个空对象,而 typeMyComponent
  • 当呈现 element时,将创建 MyComponentinstance(在上面的示例中,从构造函数中记录自己)。
  • another_element也是一个元素,它具有 keyrefpropstype属性,就像 element一样——但是这次 type的值是字符串 "div"

React 团队的博客文章 反应组件、元素和实例详细探讨了 React 拥有这三个不同概念的设计原因,我推荐阅读。

Finally, it should be noted that while the official docs are rigorous about using the term "component" to refer to a function or class and "component instance" to refer to an instance, other sources do not necessarily adhere to this terminology; you should expect to see "component" used (incorrectly) to mean "component instance" when reading Stack Overflow answers or discussions on GitHub.

组件是创建元素的工厂。

element是一个简单的对象,描述您希望在 DOM 节点或其他组件方面显示在屏幕上的内容。元素可以在其道具中包含其他元素。创建一个 React 元素是廉价的。一旦一个元素被创建,它就永远不会变异。React 元素的对象表示如下,

const element = React.createElement(
'div',
{id: 'login-btn'},
'Login'
)

上面的 createElement 返回的对象如下,

{
type: 'div',
props: {
children: 'Login',
id: 'login-btn'
}
}

最后,它使用 ReactDOM 呈现给 DOM,如下所示,

<div id='login-btn'>Login</div>

组件可以用几种不同的方式声明。它可以是一个具有 rend()方法的类。或者,在简单的情况下,它可以定义为一个函数。在这两种情况下,它都将道具作为输入,并返回一个元素树作为输出。最后,JSX 作为 createElement 发送。

function Button ({ onLogin }) {
return React.createElement(
'div',
{id: 'login-btn', onClick: onLogin},
'Login'
)
}

反应组件是可变的,而元素是不可变的

以下是我的看法:

Element描述了如何构造 VDOM,它基本上是相应 Component Instance的“冻结”版本。

如果一切都是 functional component,那么就不需要额外的反应 Elementfunctional component层次结构可以直接生成 VDOM 树。

一个反应 Component Instance层次结构(tree)是一个“工厂”,这个工厂通过提供给根反应 Component Instance的道具和 Component Instance树中任何地方的所有“存储”状态来参数化。

因此,反应 Element基本上是一个“抽象语法树”,它被编译成实际的 VDOM。

So why not generate the VDOM directly by using the react Component Instances ? This is the real question here.

乍一看,我不明白为什么做不到这一点。因此,最有可能的答案是,这是一个性能问题。

反应 Element是 VDOM 和 Component Instance之间的一个抽象层,我不完全清楚为什么需要这个抽象,它很可能允许优化。例如,如果 Component Instance上的某个生命周期方法说不需要呈现该子树,那么 Element树就不会完全呈现。

现在,在这种情况下,处理这种优化的逻辑“需要”这个额外的间接层——因为信息需要存储在某个地方,不应该将 VDOM 的某些部分与新的 VDOM 进行比较,甚至可能根本不应该计算新的 VDOM。因此,使用额外的间接层可以使呈现逻辑更简单,并导致更清晰、更易于维护的实现——我想象得到。

这个概念在哈斯克尔被称为“ 举重”:

例如,哈斯克尔的单子就是这种举升的完美例子。

单子是一种可以存储为值的计算的描述,如 42。类似地,反应 Elements是描述如何计算“新的”VDOM 的元素。如果有人想计算的话。

This talk describes this concept of an "extra" indirection with some simple 例子 :

换句话说: 过早优化是万恶之源。

或: 软件工程基本定理

软件工程基本定理(FTSE)是一个术语 来描述巴特勒 · 兰普森的一句话 attributed to the late David J. Wheeler:2

我们可以通过引入额外的间接级别来解决任何问题。

因此,在我的理解中,反应 Elements是一个实现细节,可以优雅地处理复杂性并允许一些优化(性能)。我不明白为什么人们不能摆脱这种额外的间接反应——原则上——反应仍然“一样好”——但是它可能非常缓慢,实现和维护反应“引擎”本身可能是一场噩梦。

如果我在这里遗漏了什么,请纠正我。

引用 user6445533的一个重要部分的回答:

type,表示 HTML 标记或引用 反应元件

这是关键

元素不是 VDOM。

元素就是音符。

React lets you define UIs as pure functions defined on application state. It could implement this by computing the entire UI during each state change, but this would be expensive. Elements are computational descriptions (thunks), and if they don't change, and you're using PureComponents, React won't bother recomputing that subtree.

反应元素与反应元素

反应元素

  • React Element 是从组件返回的元素。它实际上是一个描述组件所表示的 DOM 节点的对象。
  • With a function component, this element is the object that the function returns.
  • 对于类组件,元素是组件的呈现函数返回的对象
  • 反应元素不是我们在浏览器中看到的。它们只是内存中的对象,我们不能改变它们的任何东西。
  • React 元素可以具有除原生 HTML 元素之外的其他 type属性。
我们知道如下:
  • 一个反应元素描述了我们希望在屏幕上看到的内容。
更复杂的说法是:
  • A React element is an object representation of a DOM node.

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

以下几种方式反应是有益的:

  • React 可以创建和销毁这些元素,而不需要太多的开销。
  • React 可以用以前的对象表示来区分一个对象,看看发生了什么变化。
  • React 可以更新实际的 DOM,特别是它检测到的更改发生的位置。
We can create an object representation of a DOM node (aka React element) using the createElement method.
const element = React.createElement(
'div',
{id: 'login-btn'},
'Login'
)
这里 createElement包含三个参数
  1. 标记名(如 div、 span 等)
  2. 我们希望元素具有的任何属性
  3. The contents of the children of the element (eg. the text that reads Login)
The createElement invocation returns an object
{
type: 'div',
props: {
children: 'Login',
id: 'login-btn'
}
}
When this is rendered to the DOM (using ReactDOM.render), we'll have a new DOM node that looks like this:
<div id='login-btn'>Login</div>

万岁!

Huzzah

一般来说,React 是从组件优先的方法教授的,然而,理解元素优先使得向组件的平稳过渡。

反应元件

组件是可选地接受输入并返回 React 元素的函数或类。

  • React Component 是一个模板。一张蓝图。一个全球性的定义。这既可以是一个函数,也可以是一个类(带有呈现函数)。

  • 如果 response 将一个类或一个函数看作第一个参数,它将检查它呈现的是什么元素,给定相应的参数,并将继续这样做,直到不再有以类或函数作为第一个参数的 createElement调用为止。

  • 当 React 看到一个具有函数或类类型的元素时,它将与该组件进行协商,从而知道应该返回哪个元素(给定相应的道具)。

  • 在这个过程的最后,React 将拥有 DOM 树的完整对象表示。这整个过程被称为反应中的和解,每次调用 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;

用道具

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

道具可以通过 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 元素。

With 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 元素。

  • The Button component receives an onLogin method as its property.
  • 为了将它传递给 DOM 的对象表示形式,我们将它作为第二个参数传递给 createElement,就像我们对 id属性所做的那样。

我们可以用几个例子来简化这个问题。

定义框:

function Box() {
return (
// few code
)
}

如果我们执行 console.log(Box),我们说我们将一个 反应元件记录到控制台。

And if we do console.log(<Box />) we say that we are logging a 反应元素 to the console, and same thing with the following code console.log(<Box>...<Box />).

摘要:

  • Box: 反应元件。
  • <Box /><Box>...</Box>: 反应元素。