我们在讲解 JSX 的章节中提到,下面的代码:

ReactDOM.render(
<Header />,
document.getElementById('root')
)

会编译成:

ReactDOM.render(
React.createElement(Header, null),
document.getElementById('root')
)

其实我们把 Header 组件传给了 React.createElement 函数,又把函数返回结果传给了 ReactDOM.render。我们可以简单猜想一下它们会干什么事情:

// React.createElement 中实例化一个 Header
const header = new Header(props, children)
// React.createElement 中调用 header.render 方法渲染组件的内容
const headerJsxObject = header.render() // ReactDOM 用渲染后的 JavaScript 对象来来构建真正的 DOM 元素
const headerDOM = createDOMFromObject(headerJsxObject)
// ReactDOM 把 DOM 元素塞到页面上
document.getElementById('root').appendChild(headerDOM)

上面过程其实很简单,看代码就能理解。

我们把 React.js 将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载(这个定义请好好记住)。其实 React.js 内部对待每个组件都有这么一个过程,也就是初始化组件 -> 挂载到页面上的过程。所以你可以理解一个组件的方法调用是这么一个过程:

-> constructor()
-> render()
// 然后构造 DOM 元素插入页面

这当然是很好理解的。React.js 为了让我们能够更好的掌控组件的挂载过程,往上面插入了两个方法:

-> constructor()
-> componentWillMount()
-> render()
// 然后构造 DOM 元素插入页面
-> componentDidMount()

componentWillMount 和 componentDidMount 都是可以像 render 方法一样自定义在组件的内部。挂载的时候,React.js 会在组件的 render 之前调用 componentWillMount,在 DOM 元素塞入页面以后调用 componentDidMount

我们给 Header 组件加上这两个方法,并且打一些 Log:

class Header extends Component {
constructor () {
super()
console.log('construct')
} componentWillMount () {
console.log('component will mount')
} componentDidMount () {
console.log('component did mount')
} render () {
console.log('render')
return (
<div>
<h1 className='title'>React 小书</h1>
</div>
)
}
}

在控制台你可以看到依次输出:

可以看到,React.js 确实按照我们上面所说的那样调用了定义的两个方法 componentWillMount 和 componentDidMount

机灵的同学可以想到,一个组件可以插入页面,当然也可以从页面中删除。

-> constructor()
-> componentWillMount()
-> render()
// 然后构造 DOM 元素插入页面
-> componentDidMount()
// ...
// 从页面中删除

React.js 也控制了这个组件的删除过程。在组件删除之前 React.js 会调用组件定义的 componentWillUnmount

-> constructor()
-> componentWillMount()
-> render()
// 然后构造 DOM 元素插入页面
-> componentDidMount()
// ...
// 即将从页面中删除
-> componentWillUnmount()
// 从页面中删除

看看什么情况下会把组件从页面中删除,继续使用上面例子的代码,我们再定义一个 Index 组件:

class Index extends Component {
constructor() {
super()
this.state = {
isShowHeader: true
}
} handleShowOrHide () {
this.setState({
isShowHeader: !this.state.isShowHeader
})
} render () {
return (
<div>
{this.state.isShowHeader ? <Header /> : null}
<button onClick={this.handleShowOrHide.bind(this)}>
显示或者隐藏标题
</button>
</div>
)
}
} ReactDOM.render(
<Index />,
document.getElementById('root')
)

Index 组件使用了 Header 组件,并且有一个按钮,可以控制 Header 的显示或者隐藏。下面这行代码:

...a
{this.state.isShowHeader ? <Header /> : null}
...

相当于 state.isShowHeader 为 true 的时候把 Header 插入页面,false 的时候把 Header 从页面上删除。这时候我们给 Header 添加 componentWillUnmount 方法:

...
componentWillUnmount() {
console.log('component will unmount')
}
...

这时候点击页面上的按钮,你会看到页面的标题隐藏了,并且控制台打印出来下图的最后一行,说明 componentWillUnmount 确实被 React.js 所调用了:

你可以多次点击按钮,随着按钮的显示和隐藏,上面的内容会按顺序重复地打印出来,可以体会一下这几个方法的调用过程和顺序。

总结

React.js 将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载。这一节我们学习了 React.js 控制组件在页面上挂载和删除过程里面几个方法:

  • componentWillMount:组件挂载开始之前,也就是在组件调用 render 方法之前调用。
  • componentDidMount:组件挂载完成以后,也就是 DOM 元素已经插入页面后调用。
  • componentWillUnmount:组件对应的 DOM 元素从页面中删除之前调用。

但这一节并没有讲这几个方法到底在实际项目当中有什么作用,下一节我们通过例子来讲解一下这几个方法的用途。


因为第三方评论工具有问题,对本章节有任何疑问的朋友可以移步到 React.js 小书的论坛 发帖,我会回答大家的疑问。

React.js 小书 Lesson18 - 挂载阶段的组件生命周期(一)的更多相关文章

  1. React.js 小书 Lesson19 - 挂载阶段的组件生命周期(二)

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson19 转载请注明出处,保留原文链接和作者信息. 这一节我们来讨论一下对于一个组件来说,cons ...

  2. React.js 小书 Lesson20 - 更新阶段的组件生命周期

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson20 转载请注明出处,保留原文链接和作者信息. 从之前的章节我们了解到,组件的挂载指的是将组件 ...

  3. 【React.js小书】动手实现 React-redux(五):Provider - 方志

    我们要把 context 相关的代码从所有业务组件中清除出去,现在的代码里面还有一个地方是被污染的.那就是 src/index.js 里面的 Index: 1234567891011121314151 ...

  4. React.js 小书介绍

    React.js 小书 Github 关于作者 这是一本关于 React.js 的小书. 因为工作中一直在使用 React.js,也一直以来想总结一下自己关于 React.js 的一些知识.经验.于是 ...

  5. React.js 小书 Lesson16 - 实战分析:评论功能(三)

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson16 转载请注明出处,保留原文链接和作者信息. 接下来的代码比较顺理成章了.修改 Commen ...

  6. React.js小书总结

    (迁移自旧博客2017 08 27) 第一阶段 react的组件相当于MVC里面的View. react.js 将帮助我们将界面分成了各个独立的小块,每一个块就是组件,这些组件之间可以组合.嵌套,就成 ...

  7. React.js 小书 Lesson25 - 实战分析:评论功能(四)

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson25 转载请注明出处,保留原文链接和作者信息. (本文未审核) 目前为止,第二阶段知识已经基本 ...

  8. React.js 小书 Lesson26 - 实战分析:评论功能(五)

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson26 转载请注明出处,保留原文链接和作者信息. (本文未审核) 持久化评论 同样地,可以通过类 ...

  9. React.js 小书 Lesson24 - PropTypes 和组件参数验证

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson24 转载请注明出处,保留原文链接和作者信息. 我们来了到了一个非常尴尬的章节,很多初学的朋友 ...

随机推荐

  1. C#多线程编程实战1.3等待线程

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  2. angular 模板表单

  3. 温故而知新:什么是wcf

    1.什么是WCF.WCF是Windows Communication Fundation的缩写,是微软在.net 3.0 的时候引进的,用于开发可交互的分布式应用程序,是由微软发展的一组数据通信的应用 ...

  4. 去掉textarea 右下角图标 resize: none;

    如下图默认右下角有小图标: 加个样式: resize: none;就可以了:

  5. 【转】 spring context解惑

    转自:http://blog.csdn.net/c289054531/article/details/9196149?utm_source=tuicool&utm_medium=referra ...

  6. maven项目运行找不到类的错误

    Maven项目 eclipse工具 错误: [INFO] -------------------------------------------------------------[ERROR] CO ...

  7. JDBC_设计架构_驱动类加载_建立Connection_效率测试

    JDBC(Java DataBase Connection) 访问数据库流程:驱动管理器--连接数据库--sql语句--结果集 装载mysql驱动 Class.forName("com.jd ...

  8. c语言数据结构学习心得——树

    树 一对多的树型结构,有且只有一个特定的根结点. 结点的度:结点拥有子树的数量{ 度为0:叶子结点/终端结点. 度不为0:非终端结点/分支结点(除去根结点其它称为内部结点).} 树的度:树中所有结点的 ...

  9. Fundamentals of Logic

    Fundamentals of Logic To make complicated mathematical relationships clear,it is convenient to use t ...

  10. 使用C#来编写一个异步的Socket服务器

    介绍 我最近需要为一个.net项目准备一个内部线程通信机制. 项目有多个使用ASP.NET,Windows 表单和控制台应用程序的服务器和客户端构成. 考虑到实现的可能性,我下定决心要使用原生的soc ...