React 摒弃了十分消耗性能的手动DOM操作,通过控制组件state和props的改变 利用 diff算法 改变DOM,当DOM需要变动,都会先在虚拟DOM上发生,将实际发生变动的部分渲染在真实的DOM上,这样能极大的提高性能
React 中的组件本质上可以理解为是一个状态机,将状态和输出一一对应,这样可以比较直观的反应程序在不同状态时,对应什么样的输出.
组件的 生命周期 由3个部分组成:初始化阶段,运行中阶段,销毁阶段,每个阶段React都提供了不同的钩子函数供开发者使用
state属性介绍:
它是用来存储组件自身需要的数据。它是可以改变的,它的每次改变都会引发组件的更新。这也是 ReactJS 中的关键点之一。
即每次数据的更新都是通过修改 state 属性的值,然后 ReactJS 内部会监听 state 属性的变化,一旦发生变化,就会触发组件的 render 方法来更新 DOM 结构。
注意:此时 this.state 虽然获取到更新数据,但只能在内部源码中使用,我们在开发时,若在 componentWillReceiveProps 中调用 setState,那么在 componentWillReceiveProps、shouldComponentUpdate 和 componentWillUpdate 中还是无法获取到更新后的 this.state,即此时访问的this.state 仍然是未更新的数据,只有在 render 和 componentDidUpdate 中才能获取到更新后的this.state。
注意:禁止在 shouldComponentUpdate 和 componentWillUpdate 中调用 setState,会造成循环调用,直至耗光浏览器内存后崩溃。
示例代码
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
Hello, world!
It is {this.state.date.toLocaleTimeString()}.
div>
);
}
}
ReactDOM.render(
,
document.getElementById('root')
);
可以用下面这张图,来详细说明 React 组件生命周期中钩子函数 的触发顺序
初始化简单的实例
var MyFirstComponent = React.createClass({
// 只调用一次,实例之间共享引用
getDefaultProps: function () {
// 下面的console.log()是在实例化组件时就被调用
console.log('getDefaultProps, 1');
return {name: 'Tom'};
},
// 初始化每个实例特有的状态
getInitialState: function () {
console.log('getInitialState, 2');
return {ready: false};
},
// render之前最后一次修改状态的机会
componentWillMount: function () {
console.log('componentWillMount, 3');
this.setState({ready: true});
},
// 只能访问this.props和this.state,只有一个顶层组件,不可以修改状态和DOM输出
render: function () {
console.log('render, 4');
return (
"textNode">
Hello, {this.props.name ? this.props.name : 'World'}
{'' + this.state.ready}
)
},
// 成功render并渲染完成真实DOM之后触发,可以修改DOM
componentDidMount: function () {
console.log('componentDidMount, 5');
}
});
ReactDOM.render(
,
document.getElementById('example')
);
运行简单例子
var ChildComponent = React.createClass({
// 组件将要接受到属性时触发
componentWillReceiveProps: function () {
console.log('componentWillReceiveProps 1');
},
// 组件是否需要更新,返回false则阻止render调用
// 这个函数我们一般谨慎使用,只有在性能调优时会使用
shouldComponentUpdate: function () {
console.log('shouldComponentUpdate 2');
return true;
},
// 组件接收到新的props或者state后,进行渲染之前触发
// 但它不能修改props和state
componentWillUpdate: function () {
console.log('componentWillUpdate 3');
},
render: function () {
console.log('render, 4');
return (
"myText">
Hello, {this.props.name ? this.props.name : 'World'}
)
},
// 在render完成后 组件完成更新渲染到页面时触发
componentDidUpdate: function () {
console.log('componentDidUpdate 5');
// 为了演示方便,这里使用了jQuery,需要在HTML中先加载jQuery库
$(this.refs.myText).append("\nI'm here!");
}
});
var ParentComponent = React.createClass({
// 初始化状态
getInitialState: function () {
return {name: ''}
},
handleChange: function (event) {
this.setState({name: event.target.value});
},
render: function () {
return (
this.state.name} />
"form-control" type="text" onChange={this.handleChange} />
);
}
});
ReactDOM.render(
,
document.getElementById('example')
);
参考资料(https://facebook.github.io/react/docs/react-component.html)