前言 上一篇实现一个react系列二:渲染组件中说了组件是如何渲染的,本本来介绍下 react 中的生命周期。 注意,本文主要理解是去 react 中的生命周期,并没有去实现 react 中最新的生命
前言
上一篇实现一个react系列二:渲染组件中说了组件是如何渲染的,本本来介绍下react
中的生命周期。
注意,本文主要理解是去react
中的生命周期,并没有去实现react
中最新的生命周期。
生命周期
react
中生命周期是组件在不同时期运行的函数。如下图所示:(图片来源)
主要三个阶段:挂载阶段、更新阶段和卸载阶段。
实现
先将函数定义的组件和类定义的组件都转为类定义的组件,方便统一处理。
if (typeof vdom.tag === 'function') { // 将组件都转为类定义的组件, const component = createComponent(vdom, vdom.attrs) // 更新组件 props setComponentProps(component, vdom.attrs) return component.base }
- createComponent
const createComponent = (vdom, props) => { let component // 类定义的组件,直接返回实例 if (vdom.tag.prototype && vdom.tag.prototype.render) { component = new vdom.tag(props) } else { // 函数定义的组件,添加 render 方法,为了获取函数中 jsx 转化的虚拟 dom component = new vdom.tag(props) component.render = function () { return vdom.tag(props) } } return component }
- setComponentProps:更新 props
该方法用来加载及更新props
,此时,组件还没有render
,所以可以在该方法中加载componentWillMount
、componentWillReceiveProps
钩子。
const setComponentProps = (component, props) => { // 第一次渲染时,挂载 componentWillMount 钩子 if (!component.base && component.componentWillMount) { component.componentWillMount() } else if (component.base && component.componentWillReceiveProps) { // 更新阶段,props 改变时,挂载 componentWillReceiveProps 钩子 component.componentWillReceiveProps(props) } component.props = props // 渲染组件 renderComponent(component) }
- renderComponent:渲染组件
渲染组件,setState
时直接调用该方法。
const renderComponent = (component) => { // 更新阶段,挂载 shouldComponentUpdate 钩子 if (component.base && component.shouldComponentUpdate) { const bool = component.shouldComponentUpdate(component.props, component.state) if (!bool && bool !== undefined) { return false } } // 更新阶段,挂载 componentWillUpdate 钩子 if (component.base && component.componentWillUpdate) { component.componentWillUpdate() } // 获得虚拟dom const rendered = component.render() // 设置是否是更新阶段的标识符,同时也是一个真实的dom节点 const base = _render(rendered) // 更新阶段,挂载 componentDidUpdate 钩子 if (component.base && component.componentDidUpdate) { component.componentDidUpdate() } else if (component && component.componentDidMount) { // 挂载阶段,挂载 componentDidMount 钩子 component.componentDidMount() } if (component.base && component.base.parentNode) { // setState 时,新的 dom 替换掉之前的 dom component.base.parentNode.replaceChild(base, component.base) } component.base = base }
下面我们来实验下效果如何。
import React from "./react" import ReactDom from "./reactDom" class World extends React.Component { render() { return <div>{this.props.count}</div> } } class Hello extends React.Component { constructor(props) { super(props) this.state = { count: 0 } } componentWillMount() { console.log("componentWillMount") } componentDidMount() { console.log("componentDidMount") } shouldComponentUpdate(nextProps, nextState) { console.log("shouldComponentUpdate", nextProps, nextState) } componentWillUpdate() { console.log("componentWillUpdate") } componentDidUpdate() { console.log("componentDidUpdate") } addCount() { const { count } = this.state this.setState({ count: count + 1 }) } render() { console.log("render") return ( <div ha="lou"> <World count={this.state.count} /> <button onClick={this.addCount.bind(this)}> + </button> </div> ) } } ReactDom.render(<Hello />, document.getElementById("root"))
结果如下,大致样子是有了。
小结
react
的生命周期分为三个阶段,挂载阶段、更新阶段和卸载阶段。在实现时,我们先将函数定义的组件和类定义的组件都转成类定义的组件,(主要是将函数定义的组件,添加一个render
方法,获取到虚拟dom
),然后我们设置一个标识符来标识组件在什么阶段,以此来实现不同的生命周期方法。
附上本文代码