react的一些函數(shù)的官方介紹
函數(shù) / 方法
ES6中React組件是用class來定義的,關(guān)于class的知識可以看阮一峰的es6的相關(guān)介紹, 當(dāng)然描滔,如果你英文不錯也可以看React的官方介紹
// 定義一個TodoList的React組件,通過繼承React.Component來實現(xiàn)
class TodoList extends React.Component {
...
}
class的定義方法
constructor(props, context) {
super(props);
this.state = {};
}
class中的構(gòu)造器,主要功能是初始化一些變量(state等)并繼承父類(父組件)的屬性止后,需要注意的是React組件中如果有定義constructor函數(shù)就必須要寫super()
,而constructor里面如果要使用this.props的話就要super(props)
溜腐,但是就算不寫也不影響其他函數(shù)使用props因為React會自動傳入译株。
render() {
return (
<div />
);
}
渲染頁面,由于setState會觸發(fā)render挺益,所以不要在這里面setState古戴。
void componentWillMount() // unsafe, 16.4廢棄,constructor的執(zhí)行過程與之相似
在組件掛載之前調(diào)用一次矩肩。
void componentDidMount()
在組件掛載之后調(diào)用一次现恼。
void componentWillReceiveProps(nextProps) // unsafe, 16.4廢棄
父組件發(fā)生更新時被調(diào)用(不管props有沒有更新,也不管父子組件之間有沒有數(shù)據(jù)交換)
bool shouldComponentUpdate(nextProps, nextState)
判斷是否要調(diào)用render黍檩,默認(rèn)返回true叉袍,每次setState/componentWillReceiveProps觸發(fā)后調(diào)用,在比較復(fù)雜的應(yīng)用里刽酱,有一些數(shù)據(jù)的改變并不影響界面展示喳逛,可以在這里做判斷,優(yōu)化渲染效率棵里。
void componentWillUpdate(nextProps, nextState) // unsafe 16.4廢棄润文,可以用getDerivedStateFromProps替代
組件將要更新之前調(diào)用,
static getDerivedStateFromProps(props, state) // 16.3++版本
組件更新(render)之前調(diào)用殿怜,第一次初始化和無論何種方式更新組件都會調(diào)用此方法典蝌, 要注意的是 要加static
getSnapshotBeforeUpdate() // 16.3++版本
頁面之前的dom元素還沒改變之前調(diào)用,具體周期是render之后componentDidUpdate之前头谜,返回的值可以被componentDidUpdate接收
例如:
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}
void componentDidUpdate()
組件更新之后調(diào)用骏掀,除了首次render之后調(diào)用componentDidMount,其它render結(jié)束之后都是調(diào)用componentDidUpdate。
void componentWillUnmount()
組件被卸載的時候調(diào)用截驮。一般在componentDidMount里面注冊的事件需要在這里刪除笑陈。
void componentDidCatch(error, info)
可以捕獲其子組件樹和當(dāng)前生命周期里面的任何js錯誤,然后可以通過setState()顯示錯誤的UI界面
更新方式
- 首次渲染Initial Render
- 調(diào)用this.setState (并不是一次setState會觸發(fā)一次render葵袭,React可能會合并操作涵妥,再一次性進(jìn)行render)
- 父組件發(fā)生更新(一般就是props發(fā)生改變,但是就算props沒有改變或者父子組件之間沒有數(shù)據(jù)交換也會觸發(fā)render)
- 調(diào)用this.forceUpdate
React16.3版本以前的
React16.4版本以后的
一個React組件生命周期的測試?yán)?/h3>
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class TestLifeCircle extends Component {
constructor() {
super();
alert('constructor');
this.state = { name: 'Li Si' };
}
// componentWillMount() {
// alert('componentWillMount');
// }
componentDidMount() {
alert('componentDidMount');
}
componentWillUnmount() {
alert('componentWillUnmount')
}
// componentWillReceiveProps(nextProps) {
// alert('componentWillReceiveProps');
// }
shouldComponentUpdate(nextProps, nextState) {
alert('shouldComponentUpdate');
return true;
}
// componentWillUpdate() {
// alert('componentWillUpdate');
// }
componentDidUpdate() {
alert('componentDidUpdate');
}
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps: ', props, state);
alert('getDerivedStateFromProps');
}
getSnapshotBeforeUpdate() {
alert('getSnapshotBeforeUpdate');
}
setTheState() {
this.setState({ name: 'Zhang San' });
}
forceLifeCycleUpdate() {
this.forceUpdate();
}
render() {
alert('render');
const { name } = this.state;
return (
<div>
<div>Welcome {name}!</div>
</div>
);
}
}
class App extends Component {
constructor() {
super();
this.state = {};
}
parentSetState() {
this.refs.testLifeCircle.setTheState();
}
propsUpdate() {
this.setState({ data: '123' });
}
parentForceUpdate() {
this.refs.testLifeCircle.forceLifeCycleUpdate();
}
unmount() {
ReactDOM.unmountComponentAtNode(document.getElementById("app"));
}
render() {
return (
<div>
<div><button onClick={this.parentSetState.bind(this)}>setState</button></div>
<div><button onClick={this.propsUpdate.bind(this)}>props update</button></div>
<div><button onClick={this.parentForceUpdate.bind(this)}>forceUpdate</button></div>
<div><button onClick={this.unmount.bind(this)}>unmount</button></div>
<TestLifeCircle ref="testLifeCircle" />
</div>
);
}
}
ReactDom.render(
<App />,
document.getElementById('app')
);
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class TestLifeCircle extends Component {
constructor() {
super();
alert('constructor');
this.state = { name: 'Li Si' };
}
// componentWillMount() {
// alert('componentWillMount');
// }
componentDidMount() {
alert('componentDidMount');
}
componentWillUnmount() {
alert('componentWillUnmount')
}
// componentWillReceiveProps(nextProps) {
// alert('componentWillReceiveProps');
// }
shouldComponentUpdate(nextProps, nextState) {
alert('shouldComponentUpdate');
return true;
}
// componentWillUpdate() {
// alert('componentWillUpdate');
// }
componentDidUpdate() {
alert('componentDidUpdate');
}
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps: ', props, state);
alert('getDerivedStateFromProps');
}
getSnapshotBeforeUpdate() {
alert('getSnapshotBeforeUpdate');
}
setTheState() {
this.setState({ name: 'Zhang San' });
}
forceLifeCycleUpdate() {
this.forceUpdate();
}
render() {
alert('render');
const { name } = this.state;
return (
<div>
<div>Welcome {name}!</div>
</div>
);
}
}
class App extends Component {
constructor() {
super();
this.state = {};
}
parentSetState() {
this.refs.testLifeCircle.setTheState();
}
propsUpdate() {
this.setState({ data: '123' });
}
parentForceUpdate() {
this.refs.testLifeCircle.forceLifeCycleUpdate();
}
unmount() {
ReactDOM.unmountComponentAtNode(document.getElementById("app"));
}
render() {
return (
<div>
<div><button onClick={this.parentSetState.bind(this)}>setState</button></div>
<div><button onClick={this.propsUpdate.bind(this)}>props update</button></div>
<div><button onClick={this.parentForceUpdate.bind(this)}>forceUpdate</button></div>
<div><button onClick={this.unmount.bind(this)}>unmount</button></div>
<TestLifeCircle ref="testLifeCircle" />
</div>
);
}
}
ReactDom.render(
<App />,
document.getElementById('app')
);