react源码分析——自己实现生命周期

实现Component

上一章节中有讲到,当渲染的是一个类组件的时候,声明的组件都是继承Component组件的,或者PureComponent组件。

在react文件中新创建一个文件component.js文件,index.js文件中引入:

import Component from './component'

const React = {
    createElement,
    Component
}
function createElement(tag, attrs, ...children) {
    return {
        tag,
        attrs,
        children
    }
}
export default React

 Component,每一个继承于它的组件都可以直接使用this.setState()。所以这个方法应该就在Component组件中。并且状态的改变会阴气dom的重新渲染,所以这里应该调用了renderComponents函数,传递的是当前组件实例:

import { renderComponent } from '../react-dom'

class Component {
    constructor(props = {}){
        this.props = props;
        this.state={}
    }
    setState(stateChange) {
        Object.assign(this.state, stateChange);
        // 更改参数以后需要重新渲染组件
        renderComponent(this)
    }
}
export default Component;

测试一下:

import React from './react'
import ReactDOM  from './react-dom'

class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            num: 1
        }
    }
    handlerClick() {
        this.setSate({
            num: this.state.num + 1,
        })
    }
    render() {
        return (
            <div className='active'>
              {this.state.num}
              <button key='9' onClick={this.handlerClick.bind(this)}>改变状态</button>
            </div>
        )
    }
}
ReactDOM.render(<Home title='home' />, document.getElementById('app'));

点击按钮页面会发生改变。 

 

这里只是实现了状态的改变--视图的更新,但是并没有实现生命周期。

实现生命周期函数

  • componentWillMount 将要加载,还么有生成虚拟dom
  • componentDidMount 已经加载,生成虚拟的dom
  • componentWillReceiveProps 将要接收新的参数
  • componentWillUpdate 将要更新
  • componentDidUpdate 已经更新
  • componentWillUnmount 将要加载

 

 

componentWillMount和componentWillReceiveProps

componentWillMount,dom元素生成前调用,所以应该在renderComponent之前去调用

componentWillReceiveProps组件props改变,引起了重新渲染,但是还没有开始重新渲染

所以这两个周期函数会在setComeponentProps中调用。

判断有没有生成dom节点,也就是看看有没有base属性,如果已经生成,说明不是第一次渲染,是状态的更新引起的渲染,就调用componentWillReceiveProps;如果还没有生成,说明是首次加载,就调用componentWillMount周期函数。

function setComeponentProps(comp, props) {
    if(!comp.base && comp.componentWillMount ) comp.componentWillMount();
    else if(comp.componentWillReceiveProps) comp.componentWillReceiveProps();
    // 设置组件的props
    comp.props = props;
    renderComponent(comp)
}

 componentDidMount

在渲染组件的阶段,如果还没有真实的dom节点,就说明是第一次渲染,可以调用componentDidMount

componentWillUpdate

如果base属性存在,说明是重新渲染,调用,componentWillUpdate

componentDidUpdate

然后调用_render函数,渲染真是的dom节点,这里应该是渲染和更新,会在下一章节中讲更新。

在渲染组件的过程中,判断一下,base如果存在,并且父节点也存在,说明已经渲染过,这里就需要替换掉原来的节点。

渲染结束后,base存在,就可以调用componentDidUpdate函数

export function renderComponent(comp) {
    // v虚拟的dom对象
    const v = comp.render();
    console.log(v)
    const base = _render(v);
    if(comp.base && comp.componentWillUpdate) comp.componentWillUpdate();
    if(comp.base && comp.componentDidUpdate) comp.componentDidUpdate();
    else if (comp.componentDidMount) comp.componentDidMount();
    if(comp.base && comp.base.parentNode) {
        comp.base.parentNode.replaceChild(base, comp.base)
    }
    // 生成真实的dom
    comp.base = base;
}

 测试一下生命周期的调用:

 

 

import React from './react'
import ReactDOM from './react-dom'


class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            num: 1
        }
    }
    componentWillMount() {
        console.log('组件将要加载')
    }
    componentDidMount() {
        console.log('组件加载完成')
    }
    componentWillReceiveProps() {
        console.log('组件将要接受新的参数')
    }
    componentWillUpdate() {
        console.log('组件将要更新')
    }
    componentDidUpdate() {
        console.log('组件更新完成')
    }
    componentWillUnmount() {
        console.log('组件卸载')
    }
   handlerClick() {
        this.setSate({
            num: this.state.num + 1,
        })
    }
    render() {
        return (
            <div className='active'>
              {this.state.num}
              <button key='9' onClick={this.handlerClick.bind(this)}>改变状态</button>
            </div>
        )
    }
}

ReactDOM.render(<Home title='home'/>, document.getElementById('app'));

第一次渲染:

点击按钮:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值