React Component 和 React Element 有什么区别?文档提到了两者但没有详细说明,一些方法需要组件,其他元素......
React 组件和 React 元素的区别
这里涉及三种相关的事物,它们都有自己的名字:
- 组件
- 组件实例
- 元素
这有点令人惊讶,因为如果您习惯于其他 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
; 相反,它只是对要创建的组件实例的描述。这是一个对象key
,props
,ref
和type
属性。在这里,key
并且ref
有null
,props
是一个空的对象,type
是MyComponent
。- 一个实例的
MyComponent
被创建(并且,在上述例子中,从它的构造记录本身)时element
被呈现。 another_element
也是一个元素,并有key
,ref
,props
和type
刚才一样的属性element
那样-但这次的值type
是字符串"div"
。
React 团队的博客文章React Components、Elements 和 Instances中详细探讨了 React 具有这三个不同概念的设计原因,我推荐阅读。
最后,应该注意的是,虽然官方文档严格使用术语“组件”来指代函数或类,使用“组件实例”来指代实例,但其他来源不一定遵循此术语;在 GitHub 上阅读 Stack Overflow 答案或讨论时,您应该会看到“组件”使用(错误地)表示“组件实例”。
为了进一步详细说明答案,React Element 没有任何方法,原型上也没有任何内容。这也使他们快速。
“ReactElement 是 DOM 元素的轻量级、无状态、不可变的虚拟表示”——React术语表
react组件render()
函数在幕后返回react元素的 DOM 树(顺便说一下,这是虚拟 DOM)。涉及到一些复杂的映射和差异逻辑,但基本上这些 React 元素映射到 DOM 元素。
你也可以直接创建一个 Element ,React.createElement(arg)
其中 arg 可以是一个 html 标签名称,或者一个 React Component 类。
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 元素与 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
接受三个参数
- 标签名称(例如 div、span 等)
- 我们希望元素具有的任何属性
- 元素的子元素的内容(例如读取的文本
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,每次触发
setState
或ReactDOM.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
属性所做的一样。
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>
);