1. 程式人生 > 其它 >九、表單處理

九、表單處理

一、說明

下面程式碼執行後會報錯,因為在React中並不存在類似於Vue的雙向資料繫結操作

 1 import React, { Component } from "react";
 2 
 3 class App extends Component {
 4   state = {
 5     msg: "hello world",
 6   };
 7   render() {
 8     return (
 9       <div>
10         <input type="text" value={this.state.msg} />
11       </div>
12
); 13 } 14 } 15 16 export default App;

需要注意以下幾點

1、Vue中的v-model是語法糖

2、React裡使用的是單向資料流

二、受控元件

state與表單項中的value值繫結在一起,由state的值來控制表單元素的值,稱為受控元件

繫結步驟

1、新增一個state狀態,作為表單元素的value值

2、給表單元素繫結change事件,將表單元素的值設定為state的值

 1 // 案例一:
 2 import React from 'react'
 3 class Login extends React.Component{
 4
5 state = { 6 username: '', 7 password: '' 8 } 9 10 // 儲存使用者名稱到狀態中 11 saveUsername = (event) => { 12 this.setState(state => { 13 return { 14 username: event.target.value 15 } 16 }) 17 } 18 // 儲存使用者密碼到狀態中 19 savePassword = (event) => {
20 this.setState(state => { 21 return { 22 password: event.target.value 23 } 24 }) 25 } 26 // 表單提交的回撥 27 handleSubmit = (event) => { 28 event.preventDefault() 29 const {username, password} = this.state 30 //console.log(username, password) 31 } 32 33 render(){ 34 return( 35 <form 36 action="https://www.baidu.com" 37 onSubmit={handleSubmit}> 38 使用者名稱:<input 39 onChange={saveUsername} 40 type="text" 41 name="usename"/> 42 密碼:<input 43 onChange={savePassword} 44 type="text" 45 name="password"/> 46 <button>登入</button> 47 </form> 48 ) 49 } 50 } 51 export default Login;
 1 // 案例二:受控元件,使用者資訊修改
 2 import React, { Component } from "react";
 3 
 4 class App extends Component {
 5   state = {
 6     userinfo: {
 7       username: "zhangsan",
 8       mobile: "13800138000",
 9       email: "[email protected]",
10       gender: "女",
11       edm: true,
12     },
13   };
14   render() {
15     // 獲取初始的資料
16     let { username, mobile, email, gender, edm } = this.state.userinfo;
17     return (
18       <div>
19         <div>
20           <input
21             type="text"
22             value={username}
23             name="username"
24             onChange={this.changeHandler.bind(this)}/>
25         </div>
26         <div>
27           <input
28             type="text"
29             value={mobile}
30             name="mobile"
31             onChange={this.changeHandler.bind(this)}/>
32         </div>
33         <div>
34           <input
35             type="text"
36             value={email}
37             name="email"
38             onChange={this.changeHandler.bind(this)}/>
39         </div>
40         <div>
41           <input
42             type="radio"
43             value="男"
44             name="gender"
45             checked={gender === "男" ? true : false}
46             onChange={this.changeHandler.bind(this)}/>
47 48           <input
49             type="radio"
50             value="女"
51             name="gender"
52             checked={gender === "女" ? true : false}
53             onChange={this.changeHandler.bind(this)}/>
54 55         </div>
56         <div>
57           <input
58             type="checkbox"
59             name="edm"
60             checked={edm ? true : false}
61             onChange={this.changeHandler.bind(this)}/>
62           接受電子郵件營銷
63         </div>
64         <div>
65           <button onClick={this.submitForm.bind(this)}>提交</button>
66         </div>
67       </div>
68     );
69   }
70   changeHandler(e) {
71     // console.log(e.target.value);
72     let value = e.target.value;
73     let name = e.target.name;
74     let type = e.target.type;
75     this.setState((state) => {
76       if (type === "checkbox") {
77         state.userinfo[name] = !state.userinfo[name];
78         // if(state.userinfo[name]){
79         //     state.userinfo[name] = false;
80         // }else{
81         //     state.userinfo[name] = true;
82         // }
83       } else {
84         state.userinfo[name] = value;
85       }
86       return state;
87     });
88   }
89   submitForm(){
90     // 表單提交時收集表單資料
91     console.log(this.state.userinfo);
92   }
93 }
94 export default App;
  • 如果需要將原本應該分別處理的事件合在一起去寫的話,一定需要多傳遞一個引數用於記錄當前修改的是state中的哪一個值,此時可以選擇以下方案中的任意一種:
    • 通過相同name屬性值去辨別,給每個表單項設定與state中相同的key名的name值,然後通過事件物件去獲取
    • 可以直接在事件繫結的位置傳遞標記,例如:onChange={this.changeHandler.bind(this,'username')}
  • 表單項中表單項型別為checkbox的比較特殊,與其他型別的不同,需要特殊處理(取反操作,而其餘的表單項是來什麼值用什麼值)

三、非受控元件

現用現取,沒有和state資料來源進行關聯的表單項

藉助ref,使用元素DOM方式獲取表單元素值

 1 // 案例一:回撥形式的ref
 2 import React from 'react'
 3 class Login extends React.Component{
 4   
 5   handleSubmit = (event) => {
 6     event.preventDefault()
 7     const {username, password} = this
 8     console.log(username, password)
 9   }
10   
11   render(){
12     return(
13       <form
14         action="https://www.baidu.com"
15         onSubmit={handleSubmit}>
16           使用者名稱:<input
17               ref={c => this.username = c}
18               type="text"
19               name="usename"/>
20         密碼:<input
21              ref={c => this.password = c}
22              type="text"
23              name="password"/>
24         <button>登入</button>
25       </form>
26     )
27   }
28 }
29 export default Login
  • 使用步驟
    • 呼叫React.createRef()方法建立ref物件
    • 將建立好的ref物件新增到文字框中
    • 通過ref物件獲取到文字框的值

一般表單項少的時候可以考慮使用非受控元件。

非受控元件不能給表單項加value屬性,一旦加了它就不是非受控元件了,它就成了受控元件了。如果有預設值通過defaultValue屬性進行輸出。

 1 // 案例二:createRef()形式
 2 import React, { Component, createRef } from "react";
 3 
 4 class App extends Component {
 5   constructor(props) {
 6     super(props)
 7     this.username = createRef()
 8   }
 9   render() {
10     return (
11       <div>
12         <div>
13           <input type="text" defaultValue="" ref={this.username} />
14         </div>
15         <div>
16           <button onClick={this.submitForm.bind(this)}>提交</button>
17         </div>
18       </div>
19     );
20   }
21   submitForm() {
22     console.log(this.username.current.value);
23   }
24 }
25 
26 export default App;