实现自己react之添加componentWillMount和componentDidMount

本文介绍如何在自制的React库中实现componentWillMount和componentDidMount生命周期方法。通过重构mountComponent方法,确保组件生命周期中的方法得以正确调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现自己的react之简单rendering中我们实现了简单的render方法。在这节中将会为我们的Feact添加componentWillMount和componentDidMount方法。

完善createClass

在上一节中的createClass方法中只支持render方法,如下:

const Feact = {
    createClass(spec) {
        function Constructor(props) {
            this.props = props;
        }

        // 我们只是将spec的render方法赋值,忽略了其他的方法
        Constructor.prototype.render = spec.render;

        return Constructor;
    }
    ...
}

对该方法进行简单的修改,即将spec全部添加到Constructor的原型对象中。这样我们就可以获取到用户定义的所有方法了。

const Feact = {
    createClass(spec) {
        function Constructor(props) {
            this.props = props;
        }

        Constructor.prototype =
            Object.assign(Constructor.prototype, spec);

        return Constructor;
    }
    ...
}

完善mountComponent

在第一节中为了能够支持自定义组件返回组件,我们在FeactCompositeComponentWrapper#mountComponent中使用了while循环,这种方式使得生命周期的方法(比如componentWillMount)调用变得非常苦难。
第一节中的mountComponent实现如下所示:

class FeactCompositeComponentWrapper {
    constructor(element) {
        this._currentElement = element;
    }

    mountComponent(container) {
        const Component = this._currentElement.type;
        const componentInstance =
            new Component(this._currentElement.props);

        let element = componentInstance.render();

        while (typeof element.type === 'function') {
            element = (new element.type(element.props)).render();
        }

        const domComponentInstance = new FeactDOMComponent(element);
        return domComponentInstance.mountComponent(container);
    }
}

mountComponent会循环调用render方法,直到遇到原生DOM元素。这种方式的问题是子组件在整个生命周期中是不可见的,也就是说只有子组件的render方法被调用了。
将mountComponent方法进行修改为:

class FeactCompositeComponentWrapper {
    ...
    mountComponent(container) {
        const Component = this._currentElement.type;
        const componentInstance =
            new Component(this._currentElement.props);
        this._instance = componentInstance;

        const markup = this.performInitialMount(container);

        return markup;
    }

    performInitialMount(container) {
        const renderedElement = this._instance.render();

        const child = instantiateFeactComponent(renderedElement);
        this._renderedComponent = child;

        return FeactReconciler.mountComponent(child, container);
    }
}

const FeactReconciler = {
    mountComponent(internalInstance, container) {
        return internalInstance.mountComponent(container);
    }
};

function instantiateFeactComponent(element) {
    if (typeof element.type === 'string') {
        return new FeactDOMComponent(element);
    } else if (typeof element.type === 'function') {
        return new FeactCompositeComponentWrapper(element);
    }
}

这次修改看起来添加了很多的代码,实际上我们只是将mounting的代码移到了FeactReconciler中。在后续的工作中FeactReconciler会有更多的功能。
在Feact.render方法中也有mountComponent的代码,我们也使用FeactReconciler进行替换:

const Feact = {
    ...
    render(element, container) {
        const wrapperElement =
            this.createElement(TopLevelWrapper, element);

        const componentInstance =
            new FeactCompositeComponentWrapper(wrapperElement);

        return FeactReconciler.mountComponent(
            componentInstance,
            container
        );
    }
}

添加componentWillMount和componentDidMount

在做完了上面的工作后,为组件添加componentWillMount和componentDidMount生命周期的方法就非常简单了。只需要在performInitialMount方法前后添加我们的方法调用即可。

class FeactCompositeComponentWrapper {
    ...
    mountComponent(container) {
        const Component = this._currentElement.type;
        const componentInstance =
            new Component(this._currentElement.props);
        this._instance = componentInstance;

        if (componentInstance.componentWillMount) {
            componentInstance.componentWillMount();
        }

        const markUp = this.performInitialMount(container);

        if (componentInstance.componentDidMount) {
            componentInstance.componentDidMount();
        }

        return markUp;
    },
    ...
}

代码连接
原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值