通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。让我们看看它是如何运作的。

案例说明:

两个子组件都可以输入薪资,单位分别是人民币(CNY)和美金(USD). 其中一个被输入,同时会被换算(汇率按照6.65)成另一个币种显示换算后的结果. 两个组件输入的值会相互影响. 同时外部组件会根据薪资判断是否是”有钱人”.
在这里两个子组件的input值都是分别被另一个子组件共享的,所以这个值我们把它提升父级组件. 通过对父级组件的修改,从而影响另一个组件的输入. 这个就是input.value的状态提升.
b.gif
image.png

代码部分:

  1. class Salary extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.handleChange = this.handleChange.bind(this);
  5. }
  6. handleChange(e) {
  7. this.props.onChange(e.target.value);
  8. }
  9. render() {
  10. return (
  11. <div>
  12. <fieldset>
  13. <legend>薪资{this.props.cType}:</legend>
  14. <input onChange={this.handleChange} value={this.props.cValue||''}/>
  15. {this.props.cTypeIcon}
  16. </fieldset>
  17. </div>
  18. );
  19. }
  20. }
  21. class HelloWorld extends React.Component {
  22. constructor(props){
  23. super(props);
  24. this.state = {
  25. type: 'CNY',
  26. salary: 0
  27. },
  28. this.reverse = this.reverse.bind(this);
  29. this.handleCNYChange = this.handleCNYChange.bind(this);
  30. this.handleUSDChange = this.handleUSDChange.bind(this);
  31. }
  32. componentDidUpdate(){
  33. console.log(this.state);
  34. }
  35. reverse(type,salary){
  36. // 费率
  37. const C = 6.65;
  38. var outValue = 0;
  39. var inputValue = parseFloat(salary);
  40. if(Number.isNaN(inputValue)){
  41. return '';
  42. }
  43. // 转换成人民币
  44. if(type == 'CNY'){
  45. outValue = salary*C;
  46. }else{
  47. outValue = salary/C;
  48. }
  49. // 四舍五入 保留2位
  50. var roundValue = Math.round(outValue*100)/100;
  51. // 格式化
  52. if(roundValue.toString().indexOf('.')==-1){
  53. roundValue += '.00';
  54. }else{
  55. //小数部分
  56. var dotNumber = roundValue.toString().split('.')[1];
  57. dotNumber = dotNumber.length==1? dotNumber+'0': dotNumber;
  58. roundValue = roundValue.toString().split('.')[0]+'.'+dotNumber;
  59. }
  60. return roundValue;
  61. }
  62. // 人民币转换美元
  63. handleCNYChange(salary){
  64. this.setState({
  65. type: 'CNY',
  66. value: salary
  67. })
  68. }
  69. handleUSDChange(salary){
  70. this.setState({
  71. type: 'USD',
  72. value: salary
  73. })
  74. }
  75. // 判断是否是高收入
  76. areUOk(){
  77. // 人民币高于1000算高收入
  78. if(this.state.type == 'CNY'){
  79. return this.state.value>1000;
  80. }else{
  81. return this.reverse('CNY',this.state.value)>1000;
  82. }
  83. }
  84. render() {
  85. var type = this.state.type;
  86. var value = this.state.value;
  87. var CNY_value = type=='CNY'? value: this.reverse('CNY',value);
  88. var USD_value = type=='USD'? value: this.reverse('USD',value);
  89. return(
  90. <div>
  91. <Salary key="1" onChange={this.handleCNYChange} cValue={CNY_value} cType="人民币" cTypeIcon="¥"/>
  92. <Salary key="2" onChange={this.handleUSDChange} cValue={USD_value} cType="美元" cTypeIcon="$"/>
  93. <p>{this.areUOk()?'您真是有钱人!':'你还需要加油啊!'}</p>
  94. </div>
  95. )
  96. }
  97. }