关于react.js:React6React受控组件的使用

50次阅读

共计 6992 个字符,预计需要花费 18 分钟才能阅读完成。

前言

在一个理论的我的项目中,表单是必不可少的 DOM 元素。我的项目中呈现的表单元素,React 要如何获取用户在表单元素中书写或抉择的内容呢?本篇文章就为大家解说 React 中受控组件的应用办法。
受控组件:Controlled Component,组件的数据受到 state 组件状态的管制,咱们将这类组件称为“受控组件”。受控组件在应用时要实现组件数据和 state 组件状态的双向绑定。


一、文本类表单元素的受控控应用办法

文本类表单元素包含文本域、明码域、多行文本域三种表单元素。它们应用 value 属性来绑定表单元素的默认值,同时应用 onChange 事件编写当文本内容发生变化时所执行的代码。咱们将这种用法称为“value-onChange”组合。

例 1:在页面中有一个用于输出昵称的表单元素和一个按钮。用户在文本框中输出本人的昵称,单击按钮后获取用户输出的昵称内容,并在控制台中显示。

class App extends React.Component {constructor(props){super(props);
    this.state={nick:""}
  }
  render(){
    return (
      <React.Fragment>
        <label htmlFor="nick"> 昵称 </label>
        <input type="text" id="nick" value={this.state.nick} onChange={(event)=>{this.nickChange(event)}} />
        <div><button onClick={()=>this.getNick()}> 获取昵称 </button></div>
      </React.Fragment>
    )
  }
} 

从上述代码中能够看出,文本框利用 value 属性绑定了 state 区的 nick 数据作为文本框的默认值,即空字符串。同时又为文本框绑定了 onChange 事件。该事件只须要将文本框中用户输出的内容赋值给 state 区的 nick 数据即可。文本框中用户输出的内容能够应用 onChange 事件函数中的 event.tarvar.value 获取。

文本框的 onChange 事件代码如下所示。

onChange(event){
  this.setState({nick:event.target.value})
} 

按钮的单击事件代码如下所示。

getNick(){console.log(this.state.nick);
} 

从例 1 中能够看出,文本框中的 value 属性只能为文本框绑定一个初始值,当文本框中的文本内容发生变化时,还须要借助 onChange 事件来将文本框的值赋给 value 属性当初绑定的 state 数据。

例 2:在页面中有一个用于输出留言的多行文本域和一个按钮。用户在多行文本框中输出留言文本,单击按钮后获取用户输出的留言内容,并在控制台中显示。同时随着用户输出文本的增多,在页面中显示曾经输出了多少个字符,同时限度最多输出 20 个字符。

效果图如下所示。

class App extends React.Component {constructor(props){super(props);
    this.state={
      message:"",
      inputed:0,
      total:20
    }
  }
  render(){
    return (
      <React.Fragment>
        <label htmlFor="message"> 留言:(已输出 {this.state.inputed}/{this.state.total})</label>
        <textarea id="message" value={this.state.message} onChange={(event)=>{this.messageChange(event)}></textarea>
        <div><button onClick={()=>this.submitMessage()}> 提交留言 </button></div>
      </React.Fragment>
    )
  }
} 

多行文本域的解决形式和文本域的解决形式雷同,都是采纳 value-onChange 组合来实现的。当用户在多行文本域中输出内容时,将触发 onChange 事件,该事件代码如下所示。

messageChange(event){
  let message=event.target.value;
  this.setState({inputed:message.length})
  if(this.state.inputed<this.state.total-1){
    this.setState({message})
  }
} 

按钮的单击事件代码如下所示。

submitMessage(){console.log(this.state.message);
} 

在 state 区中,message 数据用来接管用户在多行文本域中输出的内容,inputed 数据用来记录曾经输出的文本个数,total 数据用来指定最多可能输出的文本个数。

二、单选框的受控应用办法

单选框在应用时持续连续文本框和多行文本框的应用形式,惟一不同的是单选框采纳的是 checked-onChange 组合来实现受控操作的。

例 3:在页面中有一组用于选择性别的单选框和一个按钮。用户抉择了某个单选项之后,单击按钮获取用户所选单选项的内容,并在控制台中显示。

class App extends Component{constructor(props){super(props);
    this.state={sex:'男'}
  } 
  render(){
    return (
        <React.Fragment>
            <label> 性别:</label>
            <input type="radio" value="男" checked={this.state.sex==="男"} onChange={(event)=>this.radioChange(event)} /> 男
            <input type="radio" value="女" checked={this.state.sex==="女"} onChange={(event)=>this.radioChange(event)} /> 女
            <div><button onClick={()=>this.getSex()}> 所选性别 </button></div>
        </React.Fragment>
    )
  }
} 

在上述代码中,每一个单选框同样具备了 value 属性,然而这个 value 属性曾经和文本框的 value 属性不一样了,这个 value 属性为单选框被选中后提供了与其余单选框所不同的数据。checked 属性取值为逻辑值,因而绑定的是 this.state.sex 是不是和指定的取值相等,相等则为 true,不相等则为 false。

单选框的 onChange 事件代码如下所示。

radioChange(event){
  this.setState({sex:event.target.value})
} 

按钮的单击事件代码如下所示。

getSex(){console.log(this.state.sex);
} 

代码中通过 checked 属性中的判断来获取哪一个单选项默认被选中,再借助 onChange 事件扭转 state 区的 sex 数据,以实现 checked 属性和 sex 数据的双向绑定。

三、复选框的受控应用办法

复选框和单选框一样,也是用 checked-onChange 组合来对其进行操作,然而复选框能够选中多个复选项,而单选框只能抉择一个,因而复选框的 checked 属性一应该绑定的是一个数组。

例 4:在页面中有一组用于抉择喜好的复选框和一个按钮。用户抉择了某些复选项之后,单击按钮获取用户所选复选项的内容,并在控制台中显示。

效果图如下所示。

class App extends Component{constructor(props){super(props);
    this.state={favs:["音乐","电影","游戏","跑步","游泳","读书"],
      fav:["电影"]
    }
  } 
  render(){
    return (
      <React.Fragment>
        <label> 喜好:</label>
          {this.state.favs.map((item,index)=>{
              return (<span key={index}>
                  <input type="checkbox" value={item} checked={this.state.fav.includes(item)} onChange={(event)=>this.checkboxChange(event)} /> {item}
                </span>
              )
          })
        }
        <div><button onClick={()=>this.getFav()}> 所选喜好 </button></div>
      </React.Fragment>
    )
  }
} 

在上述代码中,state 区定义了两个数据:favs 作为数组提供所有备选的喜好内容,fav 作为数组用来存储用户抉择的喜好内容。

  • 复选框是由 state 区的 favs 进行遍从来实现的。
  • 复选框的 checked 属性取值为逻辑值,绑定的数据是判断 favs 数组元素 item 是否在 fav 数组中,即 fav 数组中是否蕴含 favs 的数组元素 item。这里采纳的是 ES6 为数组新增的 includes() 办法,该办法间接返回参数是否蕴含在指定的数值中的逻辑值。

复选框的 onChange 事件代码如下所示。

checkboxChange(event){
  let temp=event.target.value;    // 用户选中的那一个复选框的 value 属性
  let fav=[...this.state.fav];
  let index=fav.findIndex(item=>item===temp);
  if(index!==-1){
    // 单击该复选框时,该复选框的 value 属性取值在 fav 数组中存在
    fav.splice(index,1);
  }else{
    // 单击该复选框时,该复选框的 value 属性取值在 fav 数组中不存在
    fav.push(temp);
  }
  this.setState({fav});
} 

按钮的单击事件代码如下所示。

getFav(){console.log(this.state.fav)
} 

该案例波及到了大量的数组与数组元素之间的操作。尽管同样应用 checked-onChange 组合来实现,然而两个数组 favs 和 fav 之间要进行大量的判断,能力实现最终的成果。

四、菜单的受控应用办法

<select> 菜单在表单元素中示意下拉菜单,是一个单选元素,同样应用 value-onChange 组合来进行解决。

例 5:在页面中有一组用于抉择业余的下拉菜单和一个按钮。用户抉择了某个业余之后,单击按钮获取用户所选业余的内容,并在控制台中显示。

class App extends Component{constructor(props){super(props);
    this.state={specs:["前端开发","PHP 开发","Java 开发","UI 设计","大数据开发","人工智能"],
      spec:"前端开发"
    }
  }
  render(){
    return (
      <React.Fragment>
        <label> 业余:</label>
        <select value={this.state.spec} onChange={(event)=>this.specChange(event)}>
          {this.state.specs.map((item,index)=>{return <option value={item} key={index}>{item}</option>
            })
          }
        </select>
        <div><button onClick={()=>this.getSpec()}> 所选业余 </button></div>
      </React.Fragment>
    )
  }
} 

在上述代码中,state 区定义了两个数据:specs 作为数组提供所有备选的业余内容,spec 用来存储用户抉择的业余内容,因为是单选,因而数据类型为字符串。

  • 下拉菜单的菜单项(即 <option> 标记)是由 state 区的 specs 进行遍从来实现的。
  • 因为下拉菜单项具备容器(即 <select> 标记),因而 <select> 标记的 value 属性用来绑定 state 区的 spec 数据,作为默认选中项。
  • <option> 的 value 属性而是为下拉菜单项设置被选中后的取值。

下拉菜单的 onChange 事件代码如下所示。

specChange(event){
  this.setState({spec:event.target.value})
} 

按钮的单击事件代码如下所示。

getSpec(){console.log(this.state.spec)
} 

仔细分析,下拉菜单的解决形式实质上和文本框是完全相同的。

五、列表的受控应用办法

<select> 列表在表单元素中示意列表抉择框,是一个能够复选的元素,同样应用 value-onChange 组合来进行解决。

例 6:在页面中有一组用于抉择选修课程的下拉列表和一个按钮。用户抉择了某些选修课程后,单击按钮获取用户所选的选修课程内容,并在控制台中显示。

效果图如下所示。

class App extends Component{constructor(props){super(props);
    this.state={courses:["高等数学","线性代数","概率统计","离散数学","复变函数与积分变换","关系代数"],
      course:[]}
  }
  render(){
    return (
      <React.Fragment>
        <label> 选修:</label>
        <select value={this.state.course} onChange={(event)=>this.courseChange(event)} multiple size={this.state.courses.length}>
          {this.state.courses.map((item,index)=>{return <option key={index} value={item}> {item} </option>
            })
          }
        </select>
        <div><button onClick={()=>this.getCourse()}> 所选选修课 </button></div>
      </React.Fragment>
    )
  }
} 

在上述代码中,state 区定义了两个数据:courses 作为数组提供所有备选的选修课程内容,course 用来存储用户抉择的选修课程内容,因为是多选,因而数据类型为数组。

这里提供两种不同的机制来实现 <select> 标记的 onChange 事件。

1、不借助键盘快捷键实现多选。

courseChange(event){
  let value=event.target.value;
  let course=[...this.state.course];
  // 判断 value 值是否在 course 数组中呈现过
  let index=course.findIndex(item=>item===value);
  if(index>=0){course.splice(index,1);
  }else{course.push(value);
  }
  this.setState({course});
} 

2、借助键盘快捷键实现多选。

courseChange(event){
  let options=event.target.options;
  let temp=[];   // 盛放被选中的 option 项的索引值的数组
  for(let i in options){if(options[i].selected){temp.push(i);
    }
  }
  let course=temp.map(item=>options[item].value);
  this.setState({course});
} 

上述原理造成的代码能够简化为以下 ES6 代码:

let options=event.target.options;
let course=Object.keys(options).filter(item=>options[item].selected===true).map(item=>options[item].value);
this.setState({course}); 

总结

本文是 React 系列教程的第六篇文章,次要为大家解说了 React 表单元素的受控组件操作。文本框、明码域、多行文本域、select 列表、select 菜单都是采纳 value-onChange 组合来实现受控操作的。单选框、复选框是采纳 checked-onChange 组合来实现受控操作的。同时具备复选性能的复选框和列表须要借助数组来接管用户所选的内容,操作起来较为简单。今天会为大家零碎的解说 React 中非受控表单元素的应用办法。

对于作者

小海前端,具备 18 年 Web 我的项目开发和前后台培训教训,在前端畛域著有较为零碎的培训教材,对 Vue.js、微信小程序开发、uniApp、React 等全栈开发畛域都有较为深的造诣。入住 Segmentfault,心愿可能更多的结识 Web 开发畛域的同仁,将 Web 开发鼎力的进行遍及。同时也违心与大家进行深刻的技术研究和商业单干。

正文完
 0