一、状态提升
class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.props.onTemperatureChange(e.target.value);
}
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
this.state = {temperature: '', scale: 'c'};
}
handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature});
}
handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature});
}
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
}
通过对上面这个官网提供的例子进行分析。状态提升其实就是将在不同子组件中共用的数据提升到父组件的state中做统一管理,这样的话就不用考虑如何在不同子组件之间同步数据,而是直接在父组件中处理子组件中更新后的数据,并同步到其他子组件中。
上面这个例子中,实现了一个温式摄氏度与华氏摄氏度相互转换的组件。组件的功能是,在一种类型的温度被用户修改后,另一种类型的温度能够同步进行转换。也就是说,温度这个状态是在两个不同类型的温度组件中公用的,所以可以将这个状态提升到父组件的state中。
当一种类型的温度改变时,调用父组件props传入的函数,如上述的handleCelsiusChange与handleFahrenheitChange,在其中用setState更新父组件中的状态,再通过转换函数更新对不同组件传入的prop,重新进行渲染,实现同步数据的功能。
二、组合&继承
1、包含关系
对某些无法提前知晓子组件具体内容的组件,可以使用一个特殊的prop——children来将子组件渲染到父组件中。
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
也可以不使用children,自行约定,使用另外的prop值来传入子组件
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts />
}
right={
<Chat />
} />
);
}
2、特例关系
某些组件可能是其他组件的一种特殊实例,这个时候可以对普通组件通过传入特定的prop进行定制,生成特殊组件
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome"
message="Thank you for visiting our spacecraft!" />
);
}
class形式定义的组件也同样适用,这里不做赘述。
文档中提到,在实际开发中并没有发现需要通过继承来构建组件层次的层次。这里可能由于没有接触过实际的react项目开发,理解地并不是很深,希望后面能够在实践中体会吧!