React
来源:互联网 发布:青少年编程最好的机构 编辑:程序博客网 时间:2024/06/05 14:24
- 通常,我们需要几个不同的组件来显示相同的数据变化。我们建议提升state到离它们最近的父级组件中。让我们来看看它是怎么执行的。
- 在这一小节中,我们会创建一个根据给定温度判断水是否能被烧开的温度计算器。
- 我们会以一个叫 BoilingVerdict 的组件开始。它接收摄氏温度并作为prop属性,然后显示它是否足够烧开水:
function BoilingVerdict(props) { if (props.celsius >= 100) { return <p>The water would boil.</p>; } return <p>The water would not boil.</p>;}
接下来,我们来创建一个叫做 Calculator 的组件。它渲染一个input组件,你输入温度数值,它会把温度保存在 this.state.temperature .
另外,它以当前的表单值渲染 BoilingVerdict 组件
class Calculator extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {temperature: ''}; } handleChange(e) { this.setState({temperature: e.target.value}); } render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> <BoilingVerdict celsius={parseFloat(temperature)} /> </fieldset> ); }}
增加第二个表单
- 我们有一个信需求,除了Celsius表单外,我们提供一个华氏度的表单,并且保持他们同步。
- 我们可以从 Calculatro 组件中提取一个 TemperatureInput 组件。我们会为它增加一个 scale属性,其值可以为c或f。
const scaleNames = { c: 'Celsius', f: 'Fahrenheit'}class TemperatureInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {temperature: ''}; } handleChange(e) { this.setState({temperature: e.target.value}); } render() { const temperature = this.state.temperature; const scale = this.props.scale; return ( <fieldset> <legend>Enter temperature in {scaleNames[scale]}:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); }}
- 我们现在可以改变 Calculator 组件,来渲染两个独立的温度表单:
class Calculator extends React.Component { render() { return ( <div> <TemperatureInput scale="c" /> <TemperatureInput scale="f" /> </div> ); }}
- 现在我们有两个表单了,但是当你在其中一个温度表单中填写数值,另一个表单不会更新。这与我们的需求相矛盾:我们想保持他们同步。
- 我们也不能展现 Calculator 组件中的 BoilingVerdict 组件。 Calculator 组件不知道当前的温度,因为温度隐藏在 TemperatureInput 组件里面。
编写转换函数
- 首先,我们写两个函数,来让摄氏度与华氏度互相转换。
function toCelsius(fahrenheit) { return (fahrenheit - 32) * 5 / 9;}function toFahrenheigt(celsius) { return (celsius * 9 / 5) + 32;}
- 这两个函数会转换两种温度。我们会写另一个函数来接受temperature字符串和一个转换函数作为参数,然后返回一个字符串。我们会用它基于另一个表单来计算数值。
- 当temperature非法时,它返回一个空字符串,并且它保持小数点后三位。
function tryConvert(temperaure, convert) { const input = parseFloat(temperature); if (Number.isNaN(input)) { return ''; } const output = convert(input); const rounded = Math.round(output * 1000) / 1000; return rounded.toString();}
- 例如,tryConvert(‘abc’, toCelsius)返回一个空字符串,tryConvert(‘10.22’, toFahrenheit)返回’50.396’。
提升状态
现在,两个 TemperatureInput 组件分别持有他们自己的state:
class TemperatureInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {temperature: ''}; } handleChange(e) { this.setState({temperature: e.target.value}); } render() { const temperature = this.state.temperature; }}
- 然而,我们想让这两个表单保持同步。当我们更新Celsius表单时,Fahrenheit表单应该呈现转换后的温度,反之亦然。
- 在React中,分享状态是通过移动状态到理他们最近的父级组件来完成的。这叫做“状态机提升”。我们会把当前状态从TemperatureInput组件移动到Calculator组件中。
- 如果Calculator组件拥有共享状态,它就成为当前两个温度表单的”真实来源”。这回让他们都具有值,并且一致。既然两个TemperatureInput组件的静态属性props都来自于相同的父级组件Calculator,这两个表单将会保持同步。
- 让我们看看如何一步步完成这个工作。
- 首先,在 TemperatureInput 组件中,我们用 this.props.temperature 替换 this.state.temperature。尽管它将从Calculator组件传来,现在让我们假设 this.props.temperature 已经存在:
render() { // Before: const temperature = this.state.temperature; const temperature = this.props.temperature;}
我们知道props属性是只读的。当temperature之前是本地状态时,TemperatureInput组件可以调用this.setState()来改变它。但是,现在temperature是来自于父级的props,TemperatureInput无权控制它。
- 在React中,通常用”受控”组件来解决这个问题。就想input组件同时接受value和onChange属性,自定义的TemperatureInput也可以从它的父级组件Claculator组件同时接收temperature和onTemperatureChange属性。
- 现在,当TemperatureInput组件想要更新它的温度时,它调用 this.props.onTemperatureChange :
handleChange(e) { // Before: this.setSate({temperature: e.target.value}); this.props.onTemperatureChange(e.target.value);}
阅读全文
0 0
- React
- react
- React
- REACT
- React
- react
- react
- React
- react
- react
- React
- React
- react
- React
- react
- react
- React
- React
- IMWeb提升营Day2 | 训练题7: 斐波那契数列
- Sublime Text概览
- Spring-Java事物回滚失效处理
- Swift 2.3迁到3.0的一些细节(不定期写)
- form标签中有button标签就会重新加载页面
- React
- 配置eclipse中jsp/html页面自动提示
- DeepLearning#之浅层与深层的训练(一)
- HDU1577--WisKey的眼神(扩展欧几里德)
- WAP2017春招2
- Java基础
- CentOS 自带防火墙 Firewalld 的安装与配置
- Java,Oracle,Echarts
- RS232、RS485和RS422之间的区别