無論你做什麼,都要相信自己可以做到,因為你的潛力是無限的。 把父組件的狀態變成屬性傳遞給子組件,子組件接受這個屬性,聽命於父組件。這個子組件就是叫做受控組件。在受控與非受控組件有兩種理解方案,第一:狹義上的受控與非受控,就是我們在表單中的受控與非受控組件。第二:廣義上的受控與非受控組件,就是 Rea ...
無論你做什麼,都要相信自己可以做到,因為你的潛力是無限的。
把父組件的狀態變成屬性傳遞給子組件,子組件接受這個屬性,聽命於父組件。這個子組件就是叫做受控組件。在受控與非受控組件有兩種理解方案,第一:狹義上的受控與非受控,就是我們在表單中的受控與非受控組件。第二:廣義上的受控與非受控組件,就是 React 組件的數據渲染是通過父組件傳遞過來的屬性控制的,能完全控制得住的就是受控組件,不能完全控制住的就是非受控組件。
1. 表單中非受控組件
React 要編寫一個表單非受控組件,可以使用 ref 來從 DOM 節點中獲取表單數據(訪問節點,通過節點訪問值),與狀態沒有任何關係,這種就是非受控組件。 下麵代碼使用非受控組件接受一個表單的值:
import React, { Component } from 'react'
export default class App extends Component {
myusername = React.createRef()
render() {
return (
<div>
<h4>登錄頁</h4>
{/* 這裡設置 value 後導致 input 不能輸入了。寫成 value 形式本身就是一種受控方式。被字元串 “hubert” 控制住了。*/}
<input type={"text"} ref={this.myusername} value="hubert"></input>
{/* 非受控需要通過 defaultValue 設置預設值,只是第一次設置值 */}
<input type={"text"} ref={this.myusername} defaultValue="hubert"></input>
<button onClick={()=>{
console.log(this.myusername.current.value)
}}>登錄</button>
<button onClick={()=>{
this.myusername.current.value = ""
}}>重置</button>
</div>
)
}
}
因為非受控組件將真實數據儲存在 DOM 節點中,所以在使用非受控組件時,有時候反而更容易同時集成 React 和非 React 代碼。如果你不介意代碼美觀性,並且希望快速編寫代碼,使用非受控組件往往可以減少你的代碼量。否則,你應該使用受控組件。
預設值問題:在React 渲染生命周期時,表單元素上的 value 將會覆蓋 DOM 節點中的值,在非受控組件中,你經常希望 React 能賦予組件一個初始值,但是不去控制後續的更新。在這種情況下,你可以指定一個 defaultvalue 屬性,而不是 value。
2. 表單中受控組件
現在如果有一個子組件需要拿到表單中的 value 值,該怎麼辦?這裡在輸入框值變更的時候,是不會同步、分享到子組件的,因為 render 函數是不會重新執行的。
在 HTML 中,表單元素(如 <input>
和 <select>
)通常自己維護 state,並根據用戶輸入進行更新。而在 React 中,可變狀態(mutable state)通常保存在組件的 state 屬性中,並且只能通過使用 setState() 來更新。我們可以把兩者結合起來,使 React 的 state 成為“唯一數據源”。渲染表單的 React 組件還控制著用戶輸入過程中表單發生的操作。被 React 以這種方式控制取值的表單輸入元素就叫做"受控組件”。
{/* 在輸入框值變更的時候,是不會同步、分享到子組件的 */}
<Child value={this.myusername.current.value}></Child>
// 設置成受控組件後後
<Child value={this.state.username}></Child>
import React, { Component } from 'react'
export default class App extends Component {
state = {
username: "hubert"
}
render() {
return (
<div>
<h4>登錄頁</h4>
{/* 這裡設置 value 後導致 input 不能輸入了。寫成 value 形式本身就是一種受控方式。被字元串 “hubert” 控制住了。*/}
{/* 非受控需要通過 defaultValue 設置預設值,只是第一次設置值 */}
<input type={"text"} ref={this.myusername} value={this.state.username} onChange={(evt)=>{
this.setState({
username: evt.target.value
})
}}></input>
<button onClick={()=>{
console.log(this.state.username)
}}>登錄</button>
<button onClick={()=>{
this.setState({
username:""
})
}}>重置</button>
{/* 在輸入框值變更的時候,是不會同步、分享到子組件的 */}
{/* <Child value={this.myusername.current.value}></Child> */}
</div>
)
}
}
// 在 react 中 onInput 和 onChange 事件的行為一樣的。原生 JS 則不然。