挂载阶段的组件生命周期
ReactDOM.render( <Header />, document.getElementById('root') ) //*********会编译成 ReactDOM.render( React.createElement(Header, null), document.getElementById('root') ) //*********他会做 // 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)
可以理解为,组件调用过程为:
-> constructor()
-> componentWillMount()
-> render()
// 然后构造 DOM 元素插入页面
-> componentDidMount()
我们把react.js将组件渲染,并且构造DOM元素然后塞入页面的过程称为组件的挂载。在其内部,每个组件都会经历一个过程:
初始化组件 --> 挂载组件。
挂载阶段组件的生命周期
一般来说,组件自身的状态的初始化工作会在constructor里面去做。
一些组件的启动的动作,如ajax数据的拉取操作,定时器的启动等就可以在componentWillMount里面
组件从页面上销毁时,需要清理一些数据,就会放在componentWillUnmount里面
更新阶段组件的生命周期
shouldComponentUpdate(nextProps, nextState)
:你可以通过这个方法控制组件是否重新渲染。如果返回false
组件就不会重新渲染。这个生命周期在 React.js 性能优化上非常有用。componentWillReceiveProps(nextProps)
:组件从父组件接收到新的props
之前调用。componentWillUpdate()
:组件开始重新渲染之前调用。componentDidUpdate()
:组件重新渲染并且把更改变更到真实的 DOM 以后调用。
class AutoFocusInput extends Component { componentDidMount () { this.input.focus() } render () { return ( <input ref={(input) => this.input = input} /> ) } } ReactDOM.render( <AutoFocusInput />, document.getElementById('root') )
但是原则是:能不用就不用,特别要避免用ref做react.js本身就可以帮助你做到的页面自动跟新的操作和时间监听。
dangerouslySetHTML 和 style 属性
在react.js中所有表达式插入的内容都会被自动转义,任何的html格式都会被转义掉
如:this.state = {
content: '<h1>React.js 小书</h1>'},不会以动态html格式显示,而是直接将内容显示成字符串文本。
它提供了一个属性 dangerouslySetInnerHTML
,可以让我们设置动态设置元素的 innerHTML dangerouslySetInnerHTML={{__html: this.state.content}}
React.js 中的元素的 style
属性的用法和 DOM 里面的 style
不大一样,普通的 HTML 中的:
//React.js 中的元素的 style 属性的用法和 DOM 里面的 style 不大一样,普通的 HTML 中的: <h1 style='font-size: 12px; color: red;'>React.js 小书</h1> //在 React.js 中你需要把 CSS 属性变成一个对象再传给元素: <h1 style={{fontSize: '12px', color: 'red'}}>React.js 小书</h1>
style接受一个对象,这个元素里面是这个元素的css属性键值对,原来属性中带-都去掉-换成驼峰命名。
PropTypes 和组件参数验证
JavaScript是一门灵活的语言。它的灵活性体现在弱类型,高阶函数等语言特性上。变量没有固定类型可以随意赋值,但也很容易出现bug。
react.js提供了一种给配置参数加上类型验证。
1 import React, { Component, PropTypes } from 'react' 2 3 class Comment extends Component { 4 static propTypes = { 5 comment: PropTypes.object.isRequired //可以通过isRequired
关键字来强制组件某个参数必须传入 6 } 7 8 render () { 9 const { comment } = this.props 10 return ( 11 <div className='comment'> 12 <div className='comment-user'> 13 <span>{comment.username} </span>: 14 </div> 15 <p>{comment.content}</p> 16 </div> 17 ) 18 } 19 }
//React.js 提供的PropTypes
提供了一些列的数据类型可以用来配置组件的参数:
PropTypes.array
PropTypes.bool
PropTypes.func
PropTypes.number
PropTypes.object
PropTypes.string
PropTypes.node
PropTypes.element
...
编码习惯参考
组件的私有方法都有用 _开头,所有时间监听的方法都用handle开头,把事件监听方法传给组件的时候,属性名用on开头。
1 class CommentInput extends Component { 2 constructor () { 3 super() 4 this.state = { 5 username: '', 6 content: '' 7 } 8 } 9 10 componentDidMount () { 11 this.textarea.focus() 12 } 13 14 _saveUsername (username) { 15 localStorage.setItem('username', username) 16 } 17 18 handleUsernameBlur (event) { 19 this._saveUsername(event.target.value) 20 } 21 ...
<CommentInput onSubmit={this.handleSubmitComment.bind(this)} />
另外,组件的内容编写顺序:
1.static开头的类属性,如defaultProps,propTypes;
2.构造函数,constructor;
3.getter、setter;
4.组件生命周期;
5.私有方法,以_开头;
6.事件监听方法,handle*;
7.render*开头的方法,有时候render()方法里面的内容会分开到不同的函数里面进行,这些方法都已render开头;
8.render();