React学习--受控组件与数据共享

在HTML当中,像<input>,<textarea>, 和 <select>这类表单元素会自己储存值,并且根据用户输入进行更新。但在React中,可变的值通常保存在组件的state中,并且只能用 setState() 方法进行更新。为了解决二者的矛盾,可以让HTML元素不再自己储存数据,而使用来自于react的state。也就是说HTML元素把数据保存在react组件的state中,并根据state值来渲染更新HTML的内容。这种值由React控制的表单元素称为受控组件

1、input

例如将input输入的名字保存在state.name中,并且设置input显示的value值为state.name。当input中输入变化时,onChange触发updateName函数更新name值,从而使input中显示的value发生变化。当点击提交按钮时onClick触发submit()方法来阻止默认的提交,并打印提示信息:

class ControlledForm extends React.Component{
  constructor(props){
    super(props);
    this.state={
      name:''
    };
    this.updateName=this.updateName.bind(this);
    this.submit=this.submit.bind(this);
  }

  updateName(e){                //在调用函数时会默认传入时间参数e
    this.setState({
      name:e.target.value       //更新name的值为input中输入的值
    })
  }
  submit(e){                    //自己定义点击submit后的操作
    console.log("姓名"+this.state.name+"提交成功");
    e.preventDefault();         //阻止表单默认提交行为
  }
  render(){
    return (
      <form onSubmit={this.submitForm}>
          <label>
              姓名:
              <input type="text" value={this.state.name} onChange={this.updateName} />
          </label>
          <input type="submit" value="提交" onClick={this.submit} />
      </form>
    )
  }
}

    使用受控组件使得页面的数据都处于react的控制之下,而且可以对其数据进行处理之后再渲染到页面上。

2、textarea

    在React中使用<textarea>:为了对textarea的输入内容进行控制,react中的textarea像input一样由value来控制其显示的值,并且通过e.target.value将textarea中的值存入state中。textarea的使用也由闭合式标签<textarea></textarea>变为开放式标签:

<textarea value={this.state.text} onChange={this.updateText} />

3、select

    同理,在React中的<select>也通过value来控制哪个option的选中,并通过e.target.value将选中的option的值传给state。例如和this.state.sex值相同的option会被显示选中

<select value={this.state.sex} onChange={this.updateSex}>
    <option value="male">男</option>
    <option value="female">女</option>
</select>

4、利用name处理多个受控组件

    如上,我们需要为每个受控组件都设置更新方法onChange,而且每个组件的更新方法都很类似,这样看起来很麻烦,我们可以根据name属性区分不同的组件所对应的state值,利用一个函数来实现多个组件state值的更新:

<select value={this.state.sex} name="sex" onChange={this.updateForm}>
updateForm(e){
  let name=e.target.name;         //获取组件的name
  let value=e.target.value;       //获取组件的值value
  this.setState({
    [name]:value                  //为不同name的组件设置value
  })
}

    在setState方法中,通过ES6的语法计算属性[],在中括号中指定要更新的属性名的表达式来更新不同的state。例如当select调用updateForm()时,name="sex",value="male",则通过setState将state.sex值设为male。

5、组件间数据共享

    当两个组件要同时使用一个变量时,由于state只能被它所定义的组件修改、访问,因此不能把state赋给某个组件,而应该将state提升至两个组件最近的公共父组件,父组件再通过props将值传递给子组件,这样两个子组件就都可以访问了。那么子组件怎么去修改父组件的state呢?子组件通过props属性来调用父组件的方法从而修改父组件的state,这样两个组件就通过父组件实现了对state的共享。例如父组件Parent的一个子组件ChildInput负责接收用户的输入,保存在state.text中,在另一个子组件ChildShow中显示用户的输入:

class Parent extends React.Component{
  constructor(props){
    super(props);
    this.state={
      text:''
    };
    this.updateText=this.updateText.bind(this);
  }

  updateText(value){        
    this.setState({
      text:value
    })
  }

  render(){
    return (
      <fieldset>
          <legend>提升state</legend>        //父组件updateInput属性指向updateText方法
          <ChildInput text={this.state.text} updateInput={this.updateText}/>
          <ChildShow text={this.state.text} />
      </fieldset>
    )

  }
}

class ChildInput extends React.Component{
  constructor(props){
    super(props);
    this.handleChange=this.handleChange.bind(this);
  }

  handleChange(e){       //在子组件的方法中调用父组件的updateInput更新text的值
    this.props.updateInput(e.target.value);
  }

  render(){
    return (
      <div>
          <label>
              请输入:
              <input type="text" value={this.props.text} onChange={this.handleChange}/>
          </label>
      </div>
    )
  }
}

class ChildShow extends React.Component{
  constructor(props){
    super(props);        //通过调用父组件构造方法将父组件的props传递给子组件
  }

  render(){
    return (
      <div>
          <p>输入为:{this.props.text}</p>
      </div>
    )
  }
}

ReactDOM.render(
  <Parent/>,
  document.getElementById('app')
)

运行结果如图:

上例在react中的数据流动如下:

    1、当在input中中输入内容时,input内容改变onChange触发ChildInput组件的handleChange方法,该方法通过this.props调用父组件updateInput方法并传递输入的内容e.target.value。

    2、父组件Parent在引用子组件ChildInput时为其定义updateInput属性为this.updateText方法,因此触发updateText方法,在该方法中接收子组件传递的参数value,并通过setState方法修改state.text的值。

    3、当state.text值发生改变时,父组件Parent通过属性props将值传递给子组件ChildInput与ChildShow,引起子组件属性改变,从而子组件重新渲染页面内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值