今天我們通過(guò)「龜兔賽跑」的故事,來(lái)理解React中的組件通訊。
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
allTime1: 0, // 兔子跑完全程所用時(shí)間
allTime2: 0, // 烏龜跑完全程所用時(shí)間
}
this.startTime = new Date(); // 記錄開始時(shí)間
}
success1() {
this.setState({
allTime1: new Date() - this.startTime
});
}
success2() {
this.setState({
allTime2: new Date() - this.startTime
});
}
render() {
return(
<div>
<div className="time-wrapper">
<Time1 time={this.state.allTime1}/>
<Time2 time={this.state.allTime2}/>
</div>
<Track1 success={this.success1.bind(this)}/>
<Track2 success={this.success2.bind(this)}/>
</div>
);
}
}
// 記錄兔子用時(shí)組件
class Time1 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="rabbit">
<span>??</span>
<span>{this.props.time}</span>
</div>
);
}
}
// 記錄烏龜用時(shí)組件
class Time2 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="tortoise">
<span>??</span>
<span>{this.props.time}</span>
</div>
);
}
}
class Track1 extends React.Component {
constructor(props) {
super(props);
this.state = {
style: {
transform: 'translateX(0%)'
}
};
// 初試位置
let position = 0;
// 計(jì)時(shí)器
let time = setInterval(() => {
position += 30;
if(position >= 100) {
position = 100;
clearInterval(time);
this.props.success();
}
this.setState({
style: {
transform: `translateX(${position}%)`
}
});
}, 1000);
}
render() {
return(
<div className="track-wrapper">
<div style={this.state.style}>??</div>
<div className="track"></div>
</div>
);
}
}
class Track2 extends React.Component {
constructor(props) {
super(props);
this.state = {
style: {
transform: 'translateX(0%)'
}
};
// 初試位置
let position = 0;
// 計(jì)時(shí)器
let time = setInterval(() => {
position += 20;
if(position >= 100) {
position = 100;
clearInterval(time);
this.props.success();
}
this.setState({
style: {
transform: `translateX(${position}%)`
}
});
}, 1000);
}
render() {
return(
<div className="track-wrapper">
<div style={this.state.style}>??</div>
<div className="track"></div>
</div>
);
}
}
render();
function render() {
ReactDOM.render(<App/>, document.querySelector('#root'));
}
如上圖乔夯,是組件之間的結(jié)構(gòu)圖馏鹤,相當(dāng)于一棵「樹結(jié)構(gòu)」征椒。首先在「Track1」和「Track2」中執(zhí)行由「App」傳給他倆的「success」回調(diào)函數(shù)來(lái)記錄所花時(shí)間,「App」中的state保存了「Track1」和「Track2」中執(zhí)行的時(shí)間湃累,然后傳到「Time1」和「Time2」中勃救,「Time1」和「Time2」通過(guò)「props」拿到時(shí)間渲染到組件內(nèi)。
以上圖「Track2」為例治力,當(dāng)「Track2」中的烏龜跑到終點(diǎn)后蒙秒,便調(diào)用「success」函數(shù)(圖中1處),這個(gè)函數(shù)是由「App」組件傳給「Track2」的宵统,可以通知「App」烏龜跑完所需要的時(shí)間晕讲,記錄到「Track2」的「this.state」里。再由「App」將「this.state」里面記錄的時(shí)間傳給「Time2」(圖中2處)马澈。
我再「Track1」和「Trank2」組件上加一層「PlayGround」組件瓢省。
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
allTime1: 0, // 兔子跑完全程所用時(shí)間
allTime2: 0, // 烏龜跑完全程所用時(shí)間
}
this.startTime = new Date(); // 記錄開始時(shí)間
}
success1() {
this.setState({
allTime1: new Date() - this.startTime
});
}
success2() {
this.setState({
allTime2: new Date() - this.startTime
});
}
render() {
return(
<div>
<div className="time-wrapper">
<Time1 time={this.state.allTime1}/>
<Time2 time={this.state.allTime2}/>
</div>
<PlayGround
success1={this.success1.bind(this)}
success2={this.success2.bind(this)}
/>
</div>
);
}
}
// 記錄兔子用時(shí)組件
class Time1 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="rabbit">
<span>??</span>
<span>{this.props.time}</span>
</div>
);
}
}
// 記錄烏龜用時(shí)組件
class Time2 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="tortoise">
<span>??</span>
<span>{this.props.time}</span>
</div>
);
}
}
class Track1 extends React.Component {
constructor(props) {
super(props);
this.state = {
style: {
transform: 'translateX(0%)'
}
};
// 初試位置
let position = 0;
// 計(jì)時(shí)器
let time = setInterval(() => {
position += 30;
if(position >= 100) {
position = 100;
clearInterval(time);
this.props.success();
}
this.setState({
style: {
transform: `translateX(${position}%)`
}
});
}, 1000);
}
render() {
return(
<div className="track-wrapper">
<div style={this.state.style}>??</div>
<div className="track"></div>
</div>
);
}
}
class Track2 extends React.Component {
constructor(props) {
super(props);
this.state = {
style: {
transform: 'translateX(0%)'
}
};
// 初試位置
let position = 0;
// 計(jì)時(shí)器
let time = setInterval(() => {
position += 20;
if(position >= 100) {
position = 100;
clearInterval(time);
this.props.success();
}
this.setState({
style: {
transform: `translateX(${position}%)`
}
});
}, 1000);
}
render() {
return(
<div className="track-wrapper">
<div style={this.state.style}>??</div>
<div className="track"></div>
</div>
);
}
}
class PlayGround extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className='playground'>
<Track1 success={this.props.success1}/>
<Track2 success={this.props.success2}/>
</div>
)
}
}
render();
function render() {
ReactDOM.render(<App/>, document.querySelector('#root'));
}
跟上面的功能相似,還是「App」把回調(diào)函數(shù)「success」傳到「PlayGround」組件痊班,再由「PlayGround」組件傳到「Track1」和「Track2」勤婚,「Track1」和「Track2」中調(diào)用「success」函數(shù)把時(shí)間記錄在「App」中,然后把記錄的時(shí)間從「App」中傳到「Time1」和「Time2」涤伐。