受控與非受控元件
受控與非受控元件
在 React 中,表單元素(如 <input>
、<textarea>
和 <select>
等)可以有兩種不同的方式來管理其狀態:受控元件(Controlled Components) 和 非受控元件(Uncontrolled Components)。
1. 受控元件
受控元件是指其值完全由 React 控制。表單元素的值存儲在組件的 state
中,並且當用戶進行輸入時,通過事件處理程序來更新狀態。這使得我們可以更方便地控制和驗證表單數據。
範例:受控的 <input>
元件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
}
handleChange = (event) => {
this.setState({ value: event.target.value });
};
handleSubmit = (event) => {
alert('輸入的值: ' + this.state.value);
event.preventDefault();
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
輸入文字:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<button type="submit">提交</button>
</form>
);
}
}
export default ControlledInput;
在這個例子中:
input
的值是由state
中的value
屬性控制。- 當用戶輸入時,觸發
onChange
事件處理程序來更新state
,從而使得input
的顯示值始終和state
保持同步。
受控元件的優點:
- 數據集中管理:所有表單數據都存儲在組件的
state
中,便於集中管理和處理。 - 便於數據驗證:可以在數據改變的同時進行驗證,比如限制輸入的字數或格式。
- 靈活的數據流控制:表單的數據流是單向的,方便進行邏輯處理和狀態變更。
2. 非受控元件
非受控元件不將表單的值儲存在 React 的 state
中,而是直接通過 DOM 來管理表單的值。你可以使用 React 的 ref
來獲取 DOM 元素的值,而不需要通過 state
來更新表單數據。
範例:非受控的 <input>
元件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class UncontrolledInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
handleSubmit = (event) => {
alert('輸入的值: ' + this.inputRef.current.value);
event.preventDefault();
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
輸入文字:
<input type="text" ref={this.inputRef} />
</label>
<button type="submit">提交</button>
</form>
);
}
}
export default UncontrolledInput;
在這個例子中:
- 我們使用
React.createRef()
創建了一個ref
,並將它賦值給input
元件。 - 當表單提交時,通過
ref
獲取input
的值,而不需要通過state
來存儲或控制。
非受控元件的優點:
- 簡單的實現:如果表單的邏輯很簡單,使用非受控元件會更容易,因為你不需要管理
state
。 - 適用於低頻次更新:當表單的值不需要頻繁更新或驗證時,非受控元件可以簡化代碼。
3. 受控與非受控元件的區別
特性 | 受控元件 | 非受控元件 |
---|---|---|
數據來源 | 表單的值由 React 的 state 控制。 | 表單的值直接存儲在 DOM 中。 |
值的改變 | 需要通過 onChange 事件來更新 state 。 | 不需要更新 state ,可以通過 ref 獲取值。 |
適用場景 | 當需要頻繁更新表單數據或進行即時驗證時。 | 表單邏輯簡單、不需要頻繁操作或即時驗證時。 |
數據流控制 | 更嚴格的數據流控制,便於數據管理和處理。 | 較弱的數據流控制,無需管理 state 。 |
表單驗證 | 更容易實現表單驗證和其他控制邏輯。 | 需要手動在事件處理器中實現驗證。 |
4. 受控與非受控的混合使用
有時候,你可能會需要在同一個表單中同時使用受控元件和非受控元件。例如,你可能需要將某些輸入的值直接保存在 DOM 中,而其他的輸入值則需要通過 React 的 state
來管理。
範例:混合使用受控和非受控元件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class MixedForm extends React.Component {
constructor(props) {
super(props);
this.state = { name: '' };
this.ageInputRef = React.createRef();
}
handleNameChange = (event) => {
this.setState({ name: event.target.value });
};
handleSubmit = (event) => {
alert('名稱: ' + this.state.name + ', 年齡: ' + this.ageInputRef.current.value);
event.preventDefault();
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
名稱:
<input type="text" value={this.state.name} onChange={this.handleNameChange} />
</label>
<br />
<label>
年齡:
<input type="number" ref={this.ageInputRef} />
</label>
<br />
<button type="submit">提交</button>
</form>
);
}
}
export default MixedForm;
在這個範例中:
- 名稱 (
name
) 是受控元件,由state
控制。 - 年齡 (
age
) 是非受控元件,通過ref
來獲取值。
5. 何時選擇受控或非受控元件?
- 如果你需要即時驗證、動態更新或對表單數據進行複雜處理,受控元件更合適,因為它能更好地掌控數據流。
- 如果表單較為簡單且不需要頻繁操作,可以考慮使用非受控元件,這樣可以減少不必要的狀態管理代碼。
總結
- 受控元件 通過
state
完全控制表單元素的值,適合需要即時處理或驗證的場景。 - 非受控元件 依賴於 DOM 來管理其狀態,適合簡單或低頻率更新的場景。
- 選擇使用受控或非受控元件取決於具體的應用需求。如果需要對表單進行複雜處理或驗證,受控元件會更靈活。如果表單較為簡單且不需要太多的處理,非受控元件則更輕便。
本文章以 CC BY 4.0 授權