我们在讲解 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#代码发送邮件,不完整的demo

    作为一只入行不久的小菜鸟,最近接触到利用C#代码发送邮件,做了一点小的demo练习.首先,需要配置,这边我做的是QQ邮箱的相关的练习,练习之前,首先应该解决的问题肯定是关于服务器的配置,这边偷一个懒, ...

  2. C#时常需要调用C++DLL

    在合作开发时,C#时常需要调用C++DLL,当传递参数时时常遇到问题,尤其是传递和返回字符串是,现总结一下,分享给大家: VC++中主要字符串类型为:LPSTR,LPCSTR, LPCTSTR, st ...

  3. 【bzoj1066】: [SCOI2007]蜥蜴 图论-最大流

    [bzoj1066]: [SCOI2007]蜥蜴 把石柱拆点,流量为高度 然后S与蜥蜴连流量1的边 互相能跳到的石柱连inf的边 石柱能到边界外的和T连inf的边 然后跑dinic就好了 /* htt ...

  4. HDU6299-2018ACM暑假多校联合训练1002-Balanced Sequence

    这个题的题意是给你n个字符串,认定()是一种平衡的串,两个以上连续的()()也是一种平衡的串,如果一对括号里面包含一个平衡的串,这个括号也被算在这个平衡的串之内, 如(()(()))是一个长度为8的平 ...

  5. [Swift]八大排序算法(八):基数排序

    排序分为内部排序和外部排序. 内部排序:是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 外部排序:指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存 ...

  6. numpy.histogram 官方手册

    numpy.histogram numpy.histogram(a, bins=10, range=None, normed=False, weights=None, density=None) Co ...

  7. nandflash之基本特性

    nandflash作为嵌入式中的”磁盘”, 被广泛的应用, 以(K9F2G08U0B)为例,其他型号都差不多 nandflash的结构 nandflash的结构有页(page), block(块)的概 ...

  8. P2057 [SHOI2007]善意的投票 (最大流)

    题目 P2057 [SHOI2007]善意的投票 解析 网络流的建模都如此巧妙. 我们把同意的意见看做源点\(s\),不同意的意见看做汇点\(t\). 那我们\(s\)连向所有同意的人,\(t\)连向 ...

  9. @ApiParam @PathVariable @RequestParam三者区别

    转载:https://www.cnblogs.com/xu-lei/p/7803062.html @ApiParam @PathVariable @RequestParam三者区别 1.@ApiPar ...

  10. Android 单选按钮(RadioButton)和复选框(CheckBox)的使用

    1.RadioButton (1)介绍 (2)单选按钮点击事件的用法 (3)RadioButton与RadioGroup配合使用实现单选题功能 (4)xml布局及使用 <?xml version ...