React Component

前言

在React中,一切皆组件,React的组件可以分为两种,类组件和函数式组件,它们本质上是类和函数,同样拥有原型链,继承,静态属性等特性;但与常规的类和函数不同的是,React组件承载了渲染视图的UI和更新视图的setState、useState 等方法。

React对组件处理的流程

在React调和渲染fiber节点的时候,如果发现fiber tag是ClassComponet=1,则按照类组件逻辑处理,如果是FunctionComponet=0则按照函数组件逻辑处理。当然React也提供了一些内置的组件,比如说Suspense、Profiler等。

  • 类组件的执行,是在react-reconciler/src/ReactFiberClassComponent.js中:
1
2
3
4
5
6
7
8
function constructClassInstance(
workInProgress, // 当前正在工作的 fiber 对象
ctor, // 我们的类组件
props // props
){
/* 实例化组件,得到组件实例 instance */
const instance = new ctor(props, context)
}
  • 函数式组件的执行,是在react-reconciler/src/ReactFiberHooks.js中:
1
2
3
4
5
6
7
8
9
10
11
function renderWithHooks(
current, // 当前函数组件对应的 `fiber`, 初始化
workInProgress, // 当前正在工作的 fiber 对象
Component, // 我们函数组件
props, // 函数组件第一个参数 props
secondArg, // 函数组件其他参数
nextRenderExpirationTime, //下次渲染过期时间
){
/* 执行我们的函数组件,得到 return 返回的 React.element对象 */
let children = Component(props, secondArg);
}

类组件

类组件执行执行构造函数过程中会在实例上绑定props和context,初始化置空的refs属性,原型链上绑定setState、forceUpdate方法。对于updater,React在实例化组件之后会单独绑定update对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Component(props, context, updater) {
this.props = props; //绑定props
this.context = context; //绑定context
this.refs = emptyObject; //绑定ref
this.updater = updater || ReactNoopUpdateQueue; //上面所属的updater 对象
}
/* 绑定setState 方法 */
Component.prototype.setState = function(partialState, callback) {
this.updater.enqueueSetState(this, partialState, callback, 'setState');
}
/* 绑定forceupdate 方法 */
Component.prototype.forceUpdate = function(callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
}
  • 类组件的主要组成部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Index extends React.Component{
constructor(...arg){
super(...arg) /* 执行 react 底层 Component 函数 */
}
state = {} /* state */
static number = 1 /* 内置静态属性 */
handleClick= () => console.log(111) /* 方法: 箭头函数方法直接绑定在this实例上 */
componentDidMount(){ /* 生命周期 */
console.log(Index.number,Index.number1) // 打印 1 , 2
}
render(){ /* 渲染函数 */
return <div style={{ marginTop:'50px' }} onClick={ this.handerClick } >hello,React!</div>
}
}
Index.number1 = 2 /* 外置静态属性 */
Index.prototype.handleClick = ()=> console.log(222) /* 方法: 绑定在 Index 原型链的 方法*/

函数组件

函数组件最开始又称无状态组件,在React v16.8之前只能渲染一些纯UI视图,或者通过context获取共享的状态

1
2
3
4
5
6
function Index(){
console.log(Index.number) // 打印 1
const [ message , setMessage ] = useState('hello,world') /* hooks */
return <div onClick={() => setMessage('let us learn React!') } > { message } </div> /* 返回值 作为渲染ui */
}
Index.number = 1 /* 绑定静态属性 */

通过上面的源码我们知道,React底层在执行函数组件时,是直接采用执行函数的方法,不是采用new的方法,因此不要在函数组件的原型链上绑定属性和方法。

类组件和函数组件的本质区别

  • 类组件底层只需要实例化一次,实例中保存了组件的state等状态,对于每一次更新只需要调用render方法以及对于的生命周期就可以了
  • 函数组件每一次更新都是一个新的函数执行,里面的变量都会重新声明,所以才有了React Hooks,用于保存函数组件中的状态,执行一些副作用钩子等。

组件通信方式

React组件通信方式主要有以下五种:

  • props和callback方式
  • ref方式
  • context上下文方式
  • Redux、Mobx等状态管理的方式
  • Event Bus事件总线

组件强化方式

  • 类组件继承

React的类组件,有着良好的继承性,可以先针对一些基础组件,实现一部分功能,再针对项目要求进行改造,强化,添加额外功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* 人类 */
class Person extends React.Component{
constructor(props){
super(props)
console.log('hello , i am person')
}
componentDidMount(){ console.log(1111) }
eat(){ /* 吃饭 */ }
sleep(){ /* 睡觉 */ }
ddd(){ console.log('打豆豆') /* 打豆豆 */ }
render(){
return <div>
大家好,我是一个person
</div>
}
}
/* 程序员 */
class Programmer extends Person{
constructor(props){
super(props)
console.log('hello , i am Programmer too')
}
componentDidMount(){ console.log(this) }
code(){ /* 敲代码 */ }
render(){
return <div style={ { marginTop:'50px' } } >
{ super.render() } { /* 让 Person 中的 render 执行 */ }
我还是一个程序员! { /* 添加自己的内容 */ }
</div>
}
}
export default Programmer
  • 函数组件自定义Hooks

  • HOC高阶组件

Comments