# 类组件和函数组件
React 组件分为:类组件和函数组件。
类组件:
class Demo extends React.Component {
render() {
return <span>demo</span>
}
}
函数组件:
function Demo() {
return <span>demo</span>
}
在 React 调和和渲染 fiber 节点的时候,如果 fiber tag 是 ClassComponent = 1,就按照类组件的逻辑处理,如果是 FunctionComponent = 0 则按照函数组件处理。
类组件的底层定义:
// react/src/ReactBaseClasses.js
function Component(props, context, updater) {
// 子组件必须调用 super(props),要不就找不到 props 了
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');
}
对于类组件的执行:
// react-reconciler/src/ReactFiberClassComponent.js
function constructClassInstance(
workInProgress, // 当前正在工作的 fiber 对象
ctor, // 我们的类组件
props // props
){
/* 实例化组件,得到组件实例 instance */
const instance = new ctor(props, context)
}
对于函数组件的执行:
// react-reconciler/src/ReactFiberHooks.js
function renderWithHooks(
current, // 当前函数组件对应的 `fiber`, 初始化
workInProgress, // 当前正在工作的 fiber 对象
Component, // 我们函数组件
props, // 函数组件第一个参数 props
secondArg, // 函数组件其他参数
nextRenderExpirationTime, //下次渲染过期时间
){
/* 执行我们的函数组件,得到 return 返回的 React.element对象 */
let children = Component(props, secondArg);
}
类组件各个部分的功能:
class Index extends React.Component{
constructor(...arg){
super(...arg) /* 执行 react 底层 Component 函数 */
}
state = {} /* state */
static number = 1 /* 内置静态属性 */
// 触发click的话会优先触发这个方法,因为它是绑定在实例上的
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 原型链的 方法*/
上面的 handleClick= () => console.log(111) 如果我们写成普通函数会怎样呢?
函数组件每次更新的时候都需要重新执行一次;类组件,底层只需要实例化一次,每次更新只需要调用 render 函数和相应的生命周期方法即可。
# 组件通信方式
主流通信方式:
- props 和 callback
父组件通过 props 将数据传递给子组件;子组件通过调用父组件中的方法来实现与父组件通信;
function Parent() {
const [ content, setContent ] = useState('I love you');
return <Child content={content} setContent={(val) => setContent(val)}/>
}
function Child({ content, setContent }) {
return <span onClick={() => setContent('I love you, too')}>{content}</span>
}
- ref
- React Redux等状态管理
- context
- event bus 事件总线
如果你学过 Vue 的话,看到这个是不是很熟悉。这种通信方式在 Reac 中是不推荐的:
- 需要手动绑定和解绑;
- 维护起来比较困难;