本文主要阐述下react中,Component
& Element
& ReactClass
之间的关系
下面看一段基本的代码
demo.js
import {Component} from 'react'
export deault class Demo extends Component{
render(){
return <div>{this.props.name}</div>
}
}
index.js
import React from 'react'
import Demo from './demo.js'
React.render(
<Demo name='Jenny'/>,
document.body
)
在demo文件中,我们通过ES6的语法,通过extends
继承Component
,自定义了一个组件类。here,Component
可以理解为基类,Demo
类通过继承Component而来,所以Demo实例化之后的对象可以访问到由Component继承而来的属性和方法,如setState
forceUpdate
和props
等.
在index.js
文件中,<Demo name='Jenny'/>
即为创建Element
的过程.通过这种语法实例化,得益于JSX
。抛弃JSX
,我们还可以通过以下的方式来创建ELement
:
/**React.createElement(
type,
[props],
[...children]
)**/
React.createElement(Demo, {name:'Jeny'})
在使用createElement
的时候,type参数可以是例如div
span
这样的标签字符串,也可以是一个React Component
(可以是由Component继承而来的一个组件类,也可以是一个纯函数式组件
,这里有一个问题:为什么使用函数式组件时,在内部访问不到this
)
其实第一个type
参数即为Component
的标识,像div
span
其实是React内部自建好的Coponent,从 div
到 svg
,包含了几乎所有 HTML Tags
When an element type starts with a lowercase letter, it refers to a built-in component like
or and results in a string ‘div’ or ‘span’ passed to React.createElement. Types that start with a capital letter like compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.
注:
- 即使是通过JSX来创建
Element
,在编译之后,还是会转为React.createElement
的形式** react
自定义组件首字母大写并不是必须的,只是结合JSX语法时,才需要遵守此规定(上面摘自官方文档react中JSX语法介绍)。当有首字母小写的自定义组件时,跳过JSX,直接通过React.createElement
来创建Element
即可
Element
react在解析的时候,无论是遇到div
这样的build-in component
,还是首字母大写的自定义组件,都会调用React.createElement
来为其创建element
.不同形式的element
可以相互混合。
render方法的返回值,其实就是不同种类element
的集合,即一棵element tree
,这棵树描述这着DOM的形态结构
注:组件的实例化,更新以及销毁,全由react管理,我们只是使用element来描述他们。react负责管理这些实例
element
一旦创建,就是不可更改的,就如immutableelement
并不是component
的实例,他只是一个简单的对象,我们不能在element
上调用任何实例的方法Functional components
是没有实例的。只有以类的形式声明的react
组件才有实例,而我们不需要去实例化,这个过程是交给react来管理的。在以类的形式声明component时,内部的this
即指向实例- 无论是何种形式的react组件,他们都以
props
作为输入,以element
作为输出
Reference
Understanding the Difference Between React Elements and Components