React精髓!一篇全概括小结(急速)(3)

在时钟应用的例子里,我们需要在第一次渲染到DOM的时候设置一个定时器,并且需要在相应的DOM销毁后,清除这个定时器。那么,这种情况下,React为我们提供了生命周期的钩子函数,方便我们进行使用。在React中,生命周期分为:

1)Mount 已插入真实DOM
2)Update 正在重新渲染
3)Unmount 已移出真实DOM

而相应的,生命周期钩子函数有:

componentWillMount

componentDidMount

componentWillUpdate(newProps, nextState)

componentDidUpdate(prevProps, prevState)

componentWillUnmount()

此外,还有两种特殊状态的处理函数:

componentWillReceiveProps(nextProps) 已加载的组件收到新的参数时调动

shouldComponentUpdate(nextProps, nextState) 组件判断是否重新渲染时调用

因此,基于生命周期钩子函数,我们可以实现一个时钟应用如下:

class Clock extends React.Component { constructor (props) { super(props); this.state = { date: new Date() } } tick () { this.setState({ date: new Date() }); } componentDidMount () { this.timerId = setInterval(() => { this.tick() }, 1000); } componentWillUnmount () { clearInterval(this.timerId); } render () { return ( <div>Now is {this.state.date.toLocaleTimeString()}</div> ); } }

需要注意的是:

1)render()里用不到的state,不应该声明在state里
2)不能直接使用this.state.xxx = xxx的方式来改变一个state的值,应该使用this.setState()。如:

setName () { this.setState({ name: '张不怂' }) }

this.setState()会自动覆盖this.state里相应的属性,并触发render()重新渲染。

3)状态更新可能是异步的

React可以将多个setState()调用合并成一个调用来提升性能。且由于this.props和this.state可能是异步更新的,所以不应该依靠它们的值来计算下一个状态。这种情况下,可以给setState传入一个函数,如:

this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));

9、事件处理

React元素的事件与DOM元素类似,不过也有一些区别,如:

1)React事件使用camelCase命名(onClick),而不是全小写的形式(onclick)
2)使用JSX,传入的是事件的句柄,而不是一个字符串

如以下的HTML:

<button>ADD</button>

使用React的方式描述如:

<button onClick={increment}>ADD</button>

还有一个不同在于,在原生DOM中,我们可以通过返回false来阻止默认行为,但是这在React中是行不通的,在React中需要明确使用preventDefault()来阻止默认行为。如:

function ActionLink () { function handleClick (e) { e.preventDefault(); alert('Hello, world!'); } return ( <a href="#" onClick={handleClick}>Click Me</a> ); }

这里,事件回调函数里的event是经过React特殊处理过的(遵循W3C标准),所以我们可以放心地使用它,而不用担心跨浏览器的兼容性问题。

注意: 在使用事件回调函数的时候,我们需要特别注意this的指向问题,因为在React里,除了构造函数和生命周期钩子函数里会自动绑定this为当前组件外,其他的都不会自动绑定this的指向为当前组件,因此需要我们自己注意好this的绑定问题,
通常而言,在一个类方式声明的组件里使用事件回调,我们需要在组件的constructor里绑定回调方法的this指向,如:

class Counter extends React.Component { constructor (props) { super(props); this.state = { counter: 0 } // 在这里绑定指向 this.increment = this.increment.bind(this); } increment () { this.setState({ counter: this.state.counter + 1 }); } render () { return ( <div> The counter now is: {this.state.counter} <button onClick={this.increment}>+1</button> </div> ); } }

当然,我们还有另外一种方法来使用箭头函数绑定指向,就是使用实验性的属性初始化语法,如:

class Counter extends React.Component { increment: () => { this.setState({ counter: this.state.counter + 1 }); } // ... }

3)像事件处理程序传递参数

我们可以为事件处理程序传递额外的参数,方式有以下两种:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

需要注意的是,使用箭头函数的情况下,参数e要显式传递,而使用bind的情况下,则无需显式传递(参数e会作为最后一个参数传递给事件处理程序)

10、条件渲染

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/554c22ed279c50b2e07f4241cb048d7d.html