元素(Element)
React 元素其实就是一个简单的 JS 对象。一个元素和界面上的一部分 DOM 对应,元素描述了这部分 DOM 的结构和渲染效果。
元素创建方法
有以下几种创建元素的方法:
- React.createElement
语法:
1 | React.createElement( |
参数:
type:可以是个标签名,入 div、span,也可以是个 React 组件名;
props:传入的属性;
children:第三个及之后的参数,都作为组件的子组件。
示例:
1 | const element = React.createElement( |
- React.cloneElement
React.cloneElement 和 React.createElement 相似,只不过它传入的第一个参数是个 React 元素,而不是标签名或组件。目的是基于第一个参数传入的元素复制出新的元素。
语法:
1 | React.cloneElement( |
参数:
element:要被复制的 React 元素;
props:新添加的属性;
children:新添加的子元素;
- JSX
1 | const element = <h1 className='greeting'>Hello, world</h1>; |
实际就是调用 React.createElement 创建一个新的元素,本质上是这个方法的一个语法糖。
编译后的结果为:
1 | const element = React.createElement( |
元素的本质
元素最终都会被转化成类似下面这个简单的 JS 对象:
1 | const element = { |
元素分类
- DOM 类型元素
使用 h1、div、p 等 DOM 节点创建的元素
- 组件类型元素
使用 React 组件创建的元素,例如:
1 | const buttonElement = <Button color='red'>OK</Button>; |
它对应的 JS 对象为:
1 | const buttonElement = { |
组件(Component)
React 通过组件的思想,将界面拆分成一个个可以复用的模块,一个模块就是一个组件。
组件和元素的关系密切,组件最核心的作用就是返回 React 元素。
组件分类
- 函数组件(无状态组件)
1 | function Welcome(props) { |
函数组件是最简单的组件,它和类组件最大的区别是函数本身不会被实例化。
- 类组件(有状态组件)
1 | class Welcome extends React.Component { |
类组件中,render 是唯一必须的方法,其它组件的声明周期方法都只是为了 render 服务而已。
有状态组件和无状态组件区别
无状态组件不会被实例化,无需分配多余的内存,渲染性能得到提升
无状态组件不能访问 this 对象
无状态组件不能访问声明周期方法
无状态组件智能访问输入的 props,同样的 props 会得到同样的渲染结果,不会有副作用
元素如何被渲染
渲染引擎可以通过 JS 对象里的 type 字段区分元素类型。对于 DOM 类型的元素,因为和页面的 DOM 节点直接对应,所以 React 知道如何进行渲染。但组件类型的元素,React 如何知道怎么渲染呢?
原来,当 type 的首字母是大写时,React 就会认定这是个组件。
比如下面的代码:
1 | class Home extends React.Component { |
对应的 JS 对象为:
1 | { |
当发现 Welcome 是个组件时,会根据它返回的元素决定如何渲染这个节点:
1 | { |
本质上,React 组件的复用就是为了复用组件返回的元素;React 元素是 React 应用最基础的组成单位。
实例(Instance)
React 实例指的就是组件的实例
只有类组件才有实例,函数组件不会被实例化
组件被实例化以后才有自己的 props 和 state,才持有对它 DOM 节点和子组件实例的引用
组件实例化工作由 React 自动完成,开发者不需要关心实例的创建、更新和销毁
节点(Node)
在使用 PropTypes 校验组件属性时,有这样一种类型:
1 | MyComponent.propTypes = { |
PropTypes.node 是一个 React 节点。React 节点是指可以被 React 渲染的数据类型,包括数字、字符串、React 元素或者是包含这些数据类型的数组等。