当前位置:   article > 正文

React之数据绑定以及表单处理_react 数据绑定

react 数据绑定

一、表单元素

        像<input>、<textarea>、<option>这样的表单元素不同于其他元素,因为他们可以通过用户交互发生变化。这些元素提供的界面使响应用户交互的表单数据处理更加容易

        交互属性,用户对一下元素交互时通过onChange回调函数来监听组件变化。表单元素支持几个受用户交互影响的属性:

        value用于<input>、<textarea>

        checked用于<checkbox>、<radio>

        selected用于<option>

二、受限组件和不受限组件

1.受限组件与双向数据绑定

受限组件:设置了value的<input>是一个受限组件,对于受限的<input>,渲染出来HTML元素始终保持value属性的值,此时用户在渲染出来的组件里输入任何值都不起作用

 写一个完整的表单元素的实例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>受限组件和双向绑定</title>
  7. <script src="../js/react.development.js "></script>
  8. <script src="../js/react-dom.development.js"></script>
  9. <!-- 用于解析babel -->
  10. <script src="../js/babel.min.js"></script>
  11. </head>
  12. <body>
  13. <div id="hello">
  14. </div>
  15. <div id="hello2">
  16. </div>
  17. <script type="text/babel">
  18. //受限组件,他的
  19. class Hello extends React.Component{
  20. render(){
  21. return <div>
  22. <input type="text" value='123'/>
  23. <hr/>
  24. </div>
  25. }
  26. }
  27. ReactDOM.render(<Hello />,document.getElementById('hello'))
  28. //双向数据绑定
  29. class Hello2 extends React.Component{
  30. state = {
  31. value:'12345'
  32. }
  33. //
  34. valueChange = (e)=>{
  35. this.setState({value:e.target.value})
  36. }
  37. render(){
  38. return <div>
  39. <input type="text" value={this.state.value} onChange={this.valueChange}/>
  40. <p>{this.state.value}</p>
  41. </div>
  42. }
  43. }
  44. ReactDOM.render(<Hello2 />,document.getElementById('hello2'))
  45. </script>
  46. <!-- radio、checkbox、textarea、select -->
  47. <hr/>
  48. <div id="root1"></div>
  49. <script type="text/babel">
  50. //表单元素的双向绑定
  51. class Rtx extends React.Component{
  52. state = {
  53. //单选按钮
  54. radioValue:'',
  55. //check选中的
  56. checkArr:[],
  57. //文本域的value
  58. textareaValue:'',
  59. selectArr: ['北京','上海','湖北','广东'],
  60. //select选中的地址
  61. address:''
  62. }
  63. //
  64. radioChange = (e)=>{
  65. this.setState({radioValue:e.target.value})
  66. }
  67. checkboxChange =(e)=>{
  68. //由于组件继承的是purecomponent,因此要将数组复制一次
  69. let _checkArr = [...this.state.checkArr]
  70. if (e.target.checked) {
  71. //将所有选中的复选框的value值,push到一个数组(checkArr)中
  72. _checkArr.push(e.target.value)
  73. } else {
  74. //若取消选中,则将其从checkArr中减掉
  75. _checkArr.splice(this.state.checkArr.indexOf(e.target.value), 1)
  76. }
  77. //利用setState更新checkArr
  78. this.setState({
  79. checkArr:_checkArr
  80. })
  81. }
  82. textareaChange=(e)=>{
  83. this.setState({textareaValue:e.target.value})
  84. }
  85. selectChange=(e)=>{
  86. this.setState({address:e.target.value})
  87. }
  88. submit =()=>{
  89. console.log(this.state);
  90. }
  91. render(){
  92. let checkInfo=["c1",'c2']
  93. let {radioValue,checkArr,textareaValue,selectArr,address } =this.state
  94. let {checkboxChange} =this
  95. return <div>
  96. <div>
  97. 性别:
  98. <input type="radio" value='man' checked={radioValue=='man'?true:false} onChange={this.radioChange}/>
  99. <input type="radio" value='woman' checked={radioValue=='woman'?true:false} onChange={this.radioChange}/>
  100. </div>
  101. <div>
  102. {
  103. checkInfo.map(function(item,index){
  104. return <span>
  105. {item}
  106. <input type="checkbox" name='box' value={item} key={index}
  107. onChange={checkboxChange}
  108. checked={checkArr.indexOf(item)!==-1}></input>
  109. </span>
  110. })
  111. }
  112. </div>
  113. <div>
  114. <textarea name="" id="" value={textareaValue} cols="30" rows="10" onChange={this.textareaChange}></textarea>
  115. </div>
  116. <div>
  117. 地址:
  118. <select value={address} name="address" onChange={this.selectChange}>
  119. {
  120. selectArr.map(function(item,index){
  121. return <option key={index}>{item}</option>
  122. })
  123. }
  124. </select>
  125. </div>
  126. <button disabled={!radioValue || !address || !checkArr || !textareaValue } onClick={()=>this.submit()}>提交</button>
  127. </div>
  128. }
  129. }
  130. ReactDOM.render(<Rtx />,document.getElementById('root1'))
  131. </script>
  132. <!-- radio、
  133. </body>
  134. </html>

2.不受限组件

不受限组件: 没有设置value(或者设为null)的input组件是一个不受限组件。杜宇不受限的input组件,渲染出来的元素直接反映用户输入

 使用defaultValue属性不使用value可以实现不受限组件的双向数据

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>非受限组件</title>
  7. <script src="../js/react.development.js "></script>
  8. <script src="../js/react-dom.development.js"></script>
  9. <!-- 用于解析babel -->
  10. <script src="../js/babel.min.js"></script>
  11. </head>
  12. <body>
  13. <div id="root1"></div>
  14. <script type="text/babel">
  15. //非受限组件
  16. class Rtx extends React.Component {
  17. state = {
  18. value: '123'
  19. }
  20. valueChange = (e) => {
  21. this.setState({ value: e.target.value })
  22. console.log(this.state.value);
  23. }
  24. render() {
  25. return <div>
  26. <div>
  27. <input type="text" />
  28. <input type="text" defaultValue={this.state.value} onChange={this.valueChange} />
  29. <p>{this.state.value}</p>
  30. </div>
  31. <div>
  32. 性别:
  33. <input type="radio" name='sex' value='man' />
  34. <input type="radio" name='sex' value='woman' />
  35. </div>
  36. </div>
  37. }
  38. }
  39. ReactDOM.render(<Rtx />, document.getElementById('root1'))
  40. </script>
  41. <!-- radio、checkbox、textarea、select -->
  42. <div id="root1"></div>
  43. <script type="text/babel">
  44. //表单元素的双向绑定
  45. class Rtx extends React.Component {
  46. state = {
  47. //单选按钮
  48. radioValue: '',
  49. //check选中的
  50. checkArr: [],
  51. //文本域的value
  52. textareaValue: '',
  53. selectArr: ['北京', '上海', '湖北', '广东'],
  54. //select选中的地址
  55. address: ''
  56. }
  57. //
  58. radioChange = (e) => {
  59. this.setState({ radioValue: e.target.value })
  60. }
  61. checkboxChange = (e) => {
  62. //由于组件继承的是purecomponent,因此要将数组复制一次
  63. let _checkArr = [...this.state.checkArr]
  64. if (e.target.checked) {
  65. //将所有选中的复选框的value值,push到一个数组(checkArr)中
  66. _checkArr.push(e.target.value)
  67. } else {
  68. //若取消选中,则将其从checkArr中减掉
  69. _checkArr.splice(this.state.checkArr.indexOf(e.target.value), 1)
  70. }
  71. //利用setState更新checkArr
  72. this.setState({
  73. checkArr: _checkArr
  74. })
  75. }
  76. textareaChange = (e) => {
  77. this.setState({ textareaValue: e.target.value })
  78. }
  79. selectChange = (e) => {
  80. this.setState({ address: e.target.value })
  81. }
  82. submit = () => {
  83. console.log(this.state);
  84. }
  85. render() {
  86. let checkInfo = ["c1", 'c2']
  87. let { radioValue, checkArr, textareaValue, selectArr, address } = this.state
  88. let { checkboxChange } = this
  89. return <div>
  90. <div>
  91. 性别:
  92. <input type="radio" defaultValue='man' checked={radioValue == 'man' ? true : false} onChange={this.radioChange} />
  93. <input type="radio" defaultValue='woman' checked={radioValue == 'woman' ? true : false} onChange={this.radioChange} />
  94. </div>
  95. <div>
  96. {
  97. checkInfo.map(function (item, index) {
  98. return <span>
  99. {item}
  100. <input type="checkbox" name='box' defaultValue={item} key={index}
  101. onChange={checkboxChange}
  102. checked={checkArr.indexOf(item) !== -1}></input>
  103. </span>
  104. })
  105. }
  106. </div>
  107. <div>
  108. <textarea name="" id="" value={textareaValue} cols="30" rows="10" onChange={this.textareaChange}></textarea>
  109. </div>
  110. <div>
  111. 地址:
  112. <select defaultValue={address} name="address" onChange={this.selectChange}>
  113. {
  114. selectArr.map(function (item, index) {
  115. return <option key={index}>{item}</option>
  116. })
  117. }
  118. </select>
  119. </div>
  120. <button disabled={!radioValue || !address || !checkArr || !textareaValue} onClick={() => this.submit()}>提交</button>
  121. </div>
  122. }
  123. }
  124. ReactDOM.render(<Rtx />, document.getElementById('root1'))
  125. </script>
  126. </body>
  127. </html>

三、常用表单数据绑定

对相同逻辑的表单change事件进行封装

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>表单提交</title>
  7. <script src="../js/react.development.js "></script>
  8. <script src="../js/react-dom.development.js"></script>
  9. <!-- 用于解析babel -->
  10. <script src="../js/babel.min.js"></script>
  11. </head>
  12. <body>
  13. <div id="root1"></div>
  14. <script type="text/babel">
  15. //非受限组件
  16. class Rtx extends React.Component {
  17. state = {
  18. name: 'fxt',
  19. sex:'1',
  20. address:'上海',
  21. textareaValue:'hello world'
  22. }
  23. //我们发现下面获得改变值的方法都是一样的,所以对一样的逻辑函数进行封装
  24. handleChange=(e)=>{
  25. console.log(e.target.name);
  26. let key = e.target.name
  27. this.setState({[key]:e.target.value})
  28. // this.setState({[e.target.name]:e.target.value})
  29. }
  30. // getName=(e)=>{
  31. // this.setState({name:e.target.value})
  32. // }
  33. // getSex=(e)=>{
  34. // this.setState({sex:e.target.value})
  35. // }
  36. getAddress=(e)=>{
  37. this.setState({address:e.target.value})
  38. }
  39. getTextareaValue=(e)=>{
  40. this.setState({textareaValue:e.target.value})
  41. }
  42. submit = (e) => {
  43. // e.preventDefault();
  44. alert(JSON.stringify(this.state))
  45. }
  46. render() {
  47. let selectArr=['北京', '上海', '湖北', '广东']
  48. let {name,sex,address,textareaValue}=this.state
  49. return <div>
  50. <form action="">
  51. <label for="">姓名:<input type="text" name='name' defaultValue={name} onChange={this.handleChange}/></label>
  52. <label for="">
  53. <div>
  54. 性别:
  55. <input type="radio" name="sex" value='1' defaultChecked={sex==1? true:false} id="" onChange={this.handleChange}/>
  56. <input type="radio" name="sex" value='2' defaultChecked={sex==2? true:false} id="" onChange={this.handleChange}/>
  57. </div>
  58. </label>
  59. <label for="">
  60. <div>
  61. 地址:
  62. <select defaultValue={address} name="address" onChange={this.getAddress}>
  63. {
  64. selectArr.map( (item, index) =>{
  65. return <option key={index}>{item}</option>
  66. })
  67. }
  68. </select>
  69. </div>
  70. </label>
  71. <label for="">
  72. <div>
  73. 备注:
  74. <textarea name="" id="" defaultValue={textareaValue} cols="30" rows="10" onChange={this.getTextareaValue}></textarea>
  75. </div>
  76. </label>
  77. <button disabled={!name || !address || !textareaValue || !sex} onClick={()=>{this.submit()} }>提交</button>
  78. </form>
  79. </div>
  80. }
  81. }
  82. ReactDOM.render(<Rtx />, document.getElementById('root1'))
  83. </script>
  84. </body>
  85. </html>

四、注册功能实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>注册表单验证</title>
  7. <script src="../js/react.development.js "></script>
  8. <script src="../js/react-dom.development.js"></script>
  9. <!-- 用于解析babel -->
  10. <script src="../js/babel.min.js"></script>
  11. <style>
  12. .error{
  13. color: red;
  14. }
  15. </style>
  16. </head>
  17. <body>
  18. <div id="root1"></div>
  19. <script type="text/babel">
  20. //非受限组件
  21. class Rtx extends React.Component {
  22. state = {
  23. name: '',
  24. nameError:"",
  25. passworld:'',
  26. passworldError:'',
  27. sex:'1',
  28. phone:'',
  29. phoneError:'',
  30. city:'北京',
  31. textareaValue:'hello world'
  32. }
  33. //单独写校验规则的
  34. nameChange=(e)=>{
  35. let rule= /^[\w-]{4,10}$/
  36. let value=e.target.value
  37. let error=''
  38. if(!value){
  39. error='请输入昵称'
  40. }else if(!rule.test(value)){
  41. error='请输入4-10位的昵称'
  42. }else{
  43. error=''
  44. }
  45. this.setState({
  46. name:value,
  47. nameError:error
  48. })
  49. }
  50. //进行校验的表单元素统一封装
  51. handleTest=(e)=>{
  52. let ruleArr={
  53. passworld:{
  54. rule:new RegExp(/^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/),
  55. text:'密码',
  56. error:'6-12位,至少包括一个大小写字母、数字、特殊字符'
  57. },
  58. phone:{
  59. rule:new RegExp(/^(?:(?:\+|00)86)?1[3-9]\d{9}$/),
  60. text:'手机号',
  61. error:'请输入正确的手机号'
  62. }
  63. }
  64. let value=e.target.value
  65. let key = e.target.name
  66. let ruleInfo={}
  67. let error=''
  68. Object.keys(ruleArr).map((el)=>{
  69. if(el==key){
  70. ruleInfo=ruleArr[key]
  71. }
  72. })
  73. if(!value){
  74. error='请输入'+ruleInfo.text
  75. }else if(!ruleInfo.rule.test(value)){
  76. error=ruleInfo.error
  77. }else{
  78. error=''
  79. }
  80. this.setState({
  81. [key]:value,
  82. [key+'Error']:error
  83. })
  84. }
  85. //不进行校验的表单通过自定义属性实现获得要设置的值的key键
  86. handleChange=(e)=>{
  87. console.log(e.target.name);
  88. let key = e.target.name
  89. this.setState({[key]:e.target.value})
  90. // this.setState({[e.target.name]:e.target.value})
  91. }
  92. //提交想提交值
  93. submit = (e) => {
  94. e.preventDefault()//阻止默事件
  95. let {name,passworld,sex,phone,city,textareaValue} =this.state
  96. let data={
  97. name,passworld,sex,phone,city,textareaValue
  98. }
  99. alert(JSON.stringify(data))
  100. }
  101. render() {
  102. let selectArr=[{id:1,text:'北京'},{id:2,text: '上海'}, {id:3,text:'湖北'}]
  103. let {name,nameError,passworld,passworldError,sex,phone,phoneError,city,textareaValue}=this.state
  104. return <div>
  105. <form action="">
  106. <label for="">
  107. 昵称:<input type="text" name='name' defaultValue={name} onChange={this.nameChange}/>
  108. <span className='error'> * {nameError}</span>
  109. </label>
  110. <label for="">
  111. <div>
  112. 密码:
  113. <input type="text" name='passworld' defaultValue={passworld} onChange={this.handleTest}/>
  114. <span className='error'> * {passworldError}</span>
  115. </div>
  116. </label>
  117. <label for="">
  118. <div>
  119. 性别:
  120. <input type="radio" name="sex" value='1' defaultChecked={sex==1? true:false} id="" onChange={this.handleChange}/>
  121. <input type="radio" name="sex" value='2' defaultChecked={sex==2? true:false} id="" onChange={this.handleChange}/>
  122. </div>
  123. </label>
  124. <label for="">
  125. 手机号:<input type="text" name='phone' defaultValue={phone} onChange={this.handleTest}/>
  126. <span className='error'> * {phoneError}</span>
  127. </label>
  128. <label for="">
  129. <div>
  130. 城市:
  131. <select defaultValue={city} name="city" onChange={this.handleChange}>
  132. {
  133. selectArr.map( (item, index) =>{
  134. return <option value={item.id} key={index}>{item.text}</option>
  135. })
  136. }
  137. </select>
  138. </div>
  139. </label>
  140. <label for="">
  141. <div>
  142. 备注:
  143. <textarea name="textareaValue" id="" defaultValue={textareaValue} cols="30" rows="10" onChange={this.handleChange}></textarea>
  144. </div>
  145. </label>
  146. <button disabled={!name || nameError|| !passworld || passworldError|| !sex || !phone ||phoneError || !city ||!textareaValue } onClick={this.submit }>提交</button>
  147. </form>
  148. </div>
  149. }
  150. }
  151. ReactDOM.render(<Rtx />, document.getElementById('root1'))
  152. </script>
  153. </body>
  154. </html>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/791955
推荐阅读
相关标签
  

闽ICP备14008679号