赞
踩
像<input>、<textarea>、<option>这样的表单元素不同于其他元素,因为他们可以通过用户交互发生变化。这些元素提供的界面使响应用户交互的表单数据处理更加容易
交互属性,用户对一下元素交互时通过onChange回调函数来监听组件变化。表单元素支持几个受用户交互影响的属性:
value用于<input>、<textarea>
checked用于<checkbox>、<radio>
selected用于<option>
受限组件:设置了value的<input>是一个受限组件,对于受限的<input>,渲染出来HTML元素始终保持value属性的值,此时用户在渲染出来的组件里输入任何值都不起作用
写一个完整的表单元素的实例
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>受限组件和双向绑定</title>
- <script src="../js/react.development.js "></script>
- <script src="../js/react-dom.development.js"></script>
- <!-- 用于解析babel -->
- <script src="../js/babel.min.js"></script>
- </head>
-
- <body>
- <div id="hello">
- </div>
- <div id="hello2">
- </div>
- <script type="text/babel">
- //受限组件,他的
- class Hello extends React.Component{
-
- render(){
- return <div>
- <input type="text" value='123'/>
- <hr/>
- </div>
-
- }
- }
- ReactDOM.render(<Hello />,document.getElementById('hello'))
- //双向数据绑定
- class Hello2 extends React.Component{
- state = {
- value:'12345'
- }
- //
- valueChange = (e)=>{
- this.setState({value:e.target.value})
- }
- render(){
- return <div>
- <input type="text" value={this.state.value} onChange={this.valueChange}/>
- <p>{this.state.value}</p>
- </div>
- }
- }
- ReactDOM.render(<Hello2 />,document.getElementById('hello2'))
- </script>
- <!-- radio、checkbox、textarea、select -->
- <hr/>
- <div id="root1"></div>
- <script type="text/babel">
- //表单元素的双向绑定
- class Rtx extends React.Component{
- state = {
- //单选按钮
- radioValue:'',
- //check选中的
- checkArr:[],
- //文本域的value
- textareaValue:'',
- selectArr: ['北京','上海','湖北','广东'],
- //select选中的地址
- address:''
- }
- //
- radioChange = (e)=>{
- this.setState({radioValue:e.target.value})
- }
- checkboxChange =(e)=>{
- //由于组件继承的是purecomponent,因此要将数组复制一次
- let _checkArr = [...this.state.checkArr]
- if (e.target.checked) {
- //将所有选中的复选框的value值,push到一个数组(checkArr)中
- _checkArr.push(e.target.value)
- } else {
- //若取消选中,则将其从checkArr中减掉
- _checkArr.splice(this.state.checkArr.indexOf(e.target.value), 1)
- }
- //利用setState更新checkArr
- this.setState({
- checkArr:_checkArr
- })
- }
- textareaChange=(e)=>{
- this.setState({textareaValue:e.target.value})
- }
- selectChange=(e)=>{
- this.setState({address:e.target.value})
- }
- submit =()=>{
- console.log(this.state);
- }
- render(){
- let checkInfo=["c1",'c2']
- let {radioValue,checkArr,textareaValue,selectArr,address } =this.state
- let {checkboxChange} =this
- return <div>
- <div>
- 性别:
- 男<input type="radio" value='man' checked={radioValue=='man'?true:false} onChange={this.radioChange}/>
- 女<input type="radio" value='woman' checked={radioValue=='woman'?true:false} onChange={this.radioChange}/>
- </div>
- <div>
- {
- checkInfo.map(function(item,index){
- return <span>
- {item}
- <input type="checkbox" name='box' value={item} key={index}
- onChange={checkboxChange}
- checked={checkArr.indexOf(item)!==-1}></input>
- </span>
- })
- }
- </div>
- <div>
- <textarea name="" id="" value={textareaValue} cols="30" rows="10" onChange={this.textareaChange}></textarea>
- </div>
- <div>
- 地址:
- <select value={address} name="address" onChange={this.selectChange}>
- {
- selectArr.map(function(item,index){
- return <option key={index}>{item}</option>
- })
- }
- </select>
- </div>
- <button disabled={!radioValue || !address || !checkArr || !textareaValue } onClick={()=>this.submit()}>提交</button>
- </div>
- }
- }
- ReactDOM.render(<Rtx />,document.getElementById('root1'))
- </script>
- <!-- radio、
- </body>
- </html>
不受限组件: 没有设置value(或者设为null)的input组件是一个不受限组件。杜宇不受限的input组件,渲染出来的元素直接反映用户输入
使用defaultValue属性不使用value可以实现不受限组件的双向数据
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>非受限组件</title>
- <script src="../js/react.development.js "></script>
- <script src="../js/react-dom.development.js"></script>
- <!-- 用于解析babel -->
- <script src="../js/babel.min.js"></script>
- </head>
-
- <body>
- <div id="root1"></div>
- <script type="text/babel">
- //非受限组件
- class Rtx extends React.Component {
- state = {
- value: '123'
- }
- valueChange = (e) => {
- this.setState({ value: e.target.value })
- console.log(this.state.value);
- }
- render() {
-
- return <div>
- <div>
- <input type="text" />
- <input type="text" defaultValue={this.state.value} onChange={this.valueChange} />
- <p>{this.state.value}</p>
- </div>
- <div>
- 性别:
- 男<input type="radio" name='sex' value='man' />
- 女<input type="radio" name='sex' value='woman' />
- </div>
- </div>
- }
- }
- ReactDOM.render(<Rtx />, document.getElementById('root1'))
- </script>
- <!-- radio、checkbox、textarea、select -->
- <div id="root1"></div>
- <script type="text/babel">
- //表单元素的双向绑定
- class Rtx extends React.Component {
- state = {
- //单选按钮
- radioValue: '',
- //check选中的
- checkArr: [],
- //文本域的value
- textareaValue: '',
- selectArr: ['北京', '上海', '湖北', '广东'],
- //select选中的地址
- address: ''
- }
- //
- radioChange = (e) => {
- this.setState({ radioValue: e.target.value })
- }
- checkboxChange = (e) => {
- //由于组件继承的是purecomponent,因此要将数组复制一次
- let _checkArr = [...this.state.checkArr]
- if (e.target.checked) {
- //将所有选中的复选框的value值,push到一个数组(checkArr)中
- _checkArr.push(e.target.value)
- } else {
- //若取消选中,则将其从checkArr中减掉
- _checkArr.splice(this.state.checkArr.indexOf(e.target.value), 1)
- }
- //利用setState更新checkArr
- this.setState({
- checkArr: _checkArr
- })
- }
- textareaChange = (e) => {
- this.setState({ textareaValue: e.target.value })
- }
- selectChange = (e) => {
- this.setState({ address: e.target.value })
- }
- submit = () => {
- console.log(this.state);
- }
- render() {
- let checkInfo = ["c1", 'c2']
- let { radioValue, checkArr, textareaValue, selectArr, address } = this.state
- let { checkboxChange } = this
- return <div>
- <div>
- 性别:
- 男<input type="radio" defaultValue='man' checked={radioValue == 'man' ? true : false} onChange={this.radioChange} />
- 女<input type="radio" defaultValue='woman' checked={radioValue == 'woman' ? true : false} onChange={this.radioChange} />
- </div>
- <div>
- {
- checkInfo.map(function (item, index) {
- return <span>
- {item}
- <input type="checkbox" name='box' defaultValue={item} key={index}
- onChange={checkboxChange}
- checked={checkArr.indexOf(item) !== -1}></input>
- </span>
- })
- }
- </div>
- <div>
- <textarea name="" id="" value={textareaValue} cols="30" rows="10" onChange={this.textareaChange}></textarea>
- </div>
- <div>
- 地址:
- <select defaultValue={address} name="address" onChange={this.selectChange}>
- {
- selectArr.map(function (item, index) {
- return <option key={index}>{item}</option>
- })
- }
- </select>
- </div>
- <button disabled={!radioValue || !address || !checkArr || !textareaValue} onClick={() => this.submit()}>提交</button>
- </div>
- }
- }
- ReactDOM.render(<Rtx />, document.getElementById('root1'))
- </script>
- </body>
-
- </html>
对相同逻辑的表单change事件进行封装
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>表单提交</title>
- <script src="../js/react.development.js "></script>
- <script src="../js/react-dom.development.js"></script>
- <!-- 用于解析babel -->
- <script src="../js/babel.min.js"></script>
- </head>
-
- <body>
- <div id="root1"></div>
- <script type="text/babel">
- //非受限组件
- class Rtx extends React.Component {
- state = {
- name: 'fxt',
- sex:'1',
- address:'上海',
- textareaValue:'hello world'
- }
- //我们发现下面获得改变值的方法都是一样的,所以对一样的逻辑函数进行封装
- handleChange=(e)=>{
- console.log(e.target.name);
- let key = e.target.name
- this.setState({[key]:e.target.value})
- // this.setState({[e.target.name]:e.target.value})
- }
- // getName=(e)=>{
- // this.setState({name:e.target.value})
- // }
- // getSex=(e)=>{
- // this.setState({sex:e.target.value})
- // }
- getAddress=(e)=>{
- this.setState({address:e.target.value})
- }
- getTextareaValue=(e)=>{
- this.setState({textareaValue:e.target.value})
- }
- submit = (e) => {
- // e.preventDefault();
- alert(JSON.stringify(this.state))
- }
- render() {
- let selectArr=['北京', '上海', '湖北', '广东']
- let {name,sex,address,textareaValue}=this.state
- return <div>
- <form action="">
- <label for="">姓名:<input type="text" name='name' defaultValue={name} onChange={this.handleChange}/></label>
- <label for="">
- <div>
- 性别:
- <input type="radio" name="sex" value='1' defaultChecked={sex==1? true:false} id="" onChange={this.handleChange}/>男
- <input type="radio" name="sex" value='2' defaultChecked={sex==2? true:false} id="" onChange={this.handleChange}/>女
- </div>
- </label>
- <label for="">
- <div>
- 地址:
- <select defaultValue={address} name="address" onChange={this.getAddress}>
- {
- selectArr.map( (item, index) =>{
- return <option key={index}>{item}</option>
- })
- }
- </select>
- </div>
- </label>
- <label for="">
- <div>
- 备注:
- <textarea name="" id="" defaultValue={textareaValue} cols="30" rows="10" onChange={this.getTextareaValue}></textarea>
- </div>
- </label>
- <button disabled={!name || !address || !textareaValue || !sex} onClick={()=>{this.submit()} }>提交</button>
- </form>
- </div>
- }
- }
- ReactDOM.render(<Rtx />, document.getElementById('root1'))
- </script>
- </body>
-
- </html>
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>注册表单验证</title>
- <script src="../js/react.development.js "></script>
- <script src="../js/react-dom.development.js"></script>
- <!-- 用于解析babel -->
- <script src="../js/babel.min.js"></script>
- <style>
- .error{
- color: red;
- }
- </style>
- </head>
-
- <body>
- <div id="root1"></div>
- <script type="text/babel">
- //非受限组件
- class Rtx extends React.Component {
- state = {
- name: '',
- nameError:"",
- passworld:'',
- passworldError:'',
- sex:'1',
- phone:'',
- phoneError:'',
- city:'北京',
- textareaValue:'hello world'
- }
- //单独写校验规则的
- nameChange=(e)=>{
- let rule= /^[\w-]{4,10}$/
- let value=e.target.value
- let error=''
- if(!value){
- error='请输入昵称'
- }else if(!rule.test(value)){
- error='请输入4-10位的昵称'
- }else{
- error=''
- }
- this.setState({
- name:value,
- nameError:error
- })
- }
- //进行校验的表单元素统一封装
- handleTest=(e)=>{
- let ruleArr={
- passworld:{
- rule:new RegExp(/^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/),
- text:'密码',
- error:'6-12位,至少包括一个大小写字母、数字、特殊字符'
- },
- phone:{
- rule:new RegExp(/^(?:(?:\+|00)86)?1[3-9]\d{9}$/),
- text:'手机号',
- error:'请输入正确的手机号'
- }
- }
- let value=e.target.value
- let key = e.target.name
- let ruleInfo={}
- let error=''
- Object.keys(ruleArr).map((el)=>{
- if(el==key){
- ruleInfo=ruleArr[key]
- }
- })
- if(!value){
- error='请输入'+ruleInfo.text
- }else if(!ruleInfo.rule.test(value)){
- error=ruleInfo.error
- }else{
- error=''
- }
- this.setState({
- [key]:value,
- [key+'Error']:error
- })
- }
- //不进行校验的表单通过自定义属性实现获得要设置的值的key键
- handleChange=(e)=>{
- console.log(e.target.name);
- let key = e.target.name
- this.setState({[key]:e.target.value})
- // this.setState({[e.target.name]:e.target.value})
- }
- //提交想提交值
- submit = (e) => {
- e.preventDefault()//阻止默事件
- let {name,passworld,sex,phone,city,textareaValue} =this.state
- let data={
- name,passworld,sex,phone,city,textareaValue
- }
- alert(JSON.stringify(data))
- }
- render() {
- let selectArr=[{id:1,text:'北京'},{id:2,text: '上海'}, {id:3,text:'湖北'}]
- let {name,nameError,passworld,passworldError,sex,phone,phoneError,city,textareaValue}=this.state
- return <div>
- <form action="">
- <label for="">
- 昵称:<input type="text" name='name' defaultValue={name} onChange={this.nameChange}/>
- <span className='error'> * {nameError}</span>
- </label>
- <label for="">
- <div>
- 密码:
- <input type="text" name='passworld' defaultValue={passworld} onChange={this.handleTest}/>
- <span className='error'> * {passworldError}</span>
- </div>
- </label>
- <label for="">
- <div>
- 性别:
- <input type="radio" name="sex" value='1' defaultChecked={sex==1? true:false} id="" onChange={this.handleChange}/>男
- <input type="radio" name="sex" value='2' defaultChecked={sex==2? true:false} id="" onChange={this.handleChange}/>女
- </div>
- </label>
- <label for="">
- 手机号:<input type="text" name='phone' defaultValue={phone} onChange={this.handleTest}/>
- <span className='error'> * {phoneError}</span>
- </label>
- <label for="">
- <div>
- 城市:
- <select defaultValue={city} name="city" onChange={this.handleChange}>
- {
- selectArr.map( (item, index) =>{
- return <option value={item.id} key={index}>{item.text}</option>
- })
- }
- </select>
- </div>
- </label>
- <label for="">
- <div>
- 备注:
- <textarea name="textareaValue" id="" defaultValue={textareaValue} cols="30" rows="10" onChange={this.handleChange}></textarea>
- </div>
- </label>
- <button disabled={!name || nameError|| !passworld || passworldError|| !sex || !phone ||phoneError || !city ||!textareaValue } onClick={this.submit }>提交</button>
- </form>
- </div>
- }
- }
- ReactDOM.render(<Rtx />, document.getElementById('root1'))
- </script>
- </body>
-
- </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。