React筆記9(表單)

表單

在用戶提交表單時,html的默認(rèn)行為會使這個表單跳轉(zhuǎn)到一個新頁面,在React中也是這樣。
在大多數(shù)情況下,我們都會構(gòu)建一個處理提交表單并且可以訪問輸入數(shù)據(jù)的函數(shù),實(shí)現(xiàn)這一點(diǎn)的標(biāo)準(zhǔn)的方法就是使用 “受控組件” 技術(shù)。

1.受控組件

在HTML中,像input,textareaselect,這類表單元素都會維持自身的狀態(tài),并且可以根據(jù)用戶的輸入進(jìn)行更新。
在React中,可變狀態(tài)通常保存在組件的狀態(tài)屬性中,并且只能通過setState()的方法進(jìn)行更新。

我們通過使React變成一個單一的數(shù)據(jù)源來結(jié)合兩者,React負(fù)責(zé)渲染表單的組件和后續(xù)控制表單被輸入時發(fā)生的變化。相應(yīng)的,被React的數(shù)據(jù)控制狀態(tài)的表單組件被稱為 受控組件。

demo
class NameForm extends React.Component{
    constructor(props){
        super(props);
        this.state={value:''};
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange(event){
        this.setState({
            value:event.target.value
        })
        console.log(event.target.value)
    }
    handleSubmit(event){
        alert('name:'+this.state.value);
        event.preventDefault();
    }
    render(){
        return(
            <form action="">
                <label htmlFor="">
                    Name:
                    <input type="text" value={this.state.value} onChange={this.handleChange}/>
                </label>
                <input type="button" value="Submit" onClick={this.handleSubmit}/>
            </form>
        )
    }
}

ReactDOM.render(
    <NameForm />,document.getElementById('root')
)

由于value的值是在表單上設(shè)定的this.state.value,所以顯示的值始終綁定與React的state狀態(tài),并且每次按鍵輸入都會觸發(fā)this.handleChange()來更新React的state,所以展示的值也會一直更新。

使用 “受控組件” 每個狀態(tài)的改變,都有一個與他相關(guān)的處理函數(shù),這樣就能直接修改或者驗(yàn)證用戶的輸入。
例如:限制全部的輸入為 大寫字母

//修改handleChange方法
handleChange(event){
    this.setState({
        value:event.target.value.toUpperCase()
    })
}
2.textarea標(biāo)簽

①在HTML中元素通過他的子節(jié)點(diǎn)來定義它的內(nèi)容

<textarea>hello,React</ textarea>

②在React中,會使用value屬性來代替

class EssayForm extends React.Component{
    constructor(props){
        super(props);
        this.state={
            value:'please write an essay'
        }
        this.handleChange=this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this)
    }
    handleChange(event){
        this.setState({value:event.target.value})
    }
    handleSubmit(event){
        alert('essay:'+this.state.value);
        event.preventDefault();
    }
    render(){
        return(
            <form onSubmit={this.handleSubmit}>
                <label htmlFor="">
                    Name:
                    <textarea value={this.state.value} onChange={this.handleChange} />
                </label>
                <input type="submit" value="Submit"/>
            </form>
        )
    }
}

ReactDOM.render(
    <EssayForm />,document.getElementById('root')
)

注意this.state.value是在構(gòu)造函數(shù)中初始化,這樣文本區(qū)域就能獲取到其中的文本。

3.select標(biāo)簽

①在HTML中,select會創(chuàng)建一個下拉列表,比如這個HTML就創(chuàng)建了一個下拉列表的原型。

<select>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
  <option selected value="coconut">Coconut</option>
  <option value="mango">Mango</option>
</select>

注意:
Coconut選項(xiàng)上的select由于最初被選中有一個selected屬性,在React中,并不會這樣使用,而是根據(jù)select上的value來顯示選中項(xiàng),這在受控組件中更加方便,因?yàn)槟阒恍枰谝粋€地方修改他的狀態(tài)。

demo
class FlavorForm extends React.Component{
    constructor(props){
        super(props);
        this.state={value:'coconut'};
        this.handleChange=this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange(event){
        this.setState({value:event.target.value})
    }
    handleSubmit(event){
        alert('choice:'+this.state.value);
        event.preventDefault();
    }
    render(){
        return(
            <form action="" onSubmit={this.handleSubmit}>
                <label htmlFor="">
                    pick your item
                    <select value={this.state.value} onChange={this.handleChange}>
                        <option value="grapefruit">grapefruit</option>
                        <option value="lime">lime</option>
                        <option value="coconut">coconut</option>
                        <option value="mango">mango</option>
                    </select>
                </label>
                <input type="submit" value="Submit"/>
            </form>
        )
    }
}

ReactDOM.render(
    <FlavorForm />,document.getElementById('root')
)

總之,<input type="text">,<textarea>, 和 <select> 都十分類似 - 他們都通過傳入一個value屬性來實(shí)現(xiàn)對組件的控制。

4.file input標(biāo)簽

①在HTML中,<input type="file" />允許用戶從他們的存儲設(shè)備中選擇一個或者多個的文件以提交表單的形式提交到服務(wù)器,或者通過 Javascript 的 File API 對文件進(jìn)行操作 。

<input type="file">

由于該標(biāo)簽的 value 屬性是只讀的, 所以它是 React 中的一個非受控組件。我們會把它和其他非受控組件一起在后面的章節(jié)進(jìn)行詳細(xì)的介紹。

5.多個輸入的解決方法

當(dāng)你處理多個受控的input組件時,可以通過給每一個元素添加name屬性,來讓處理函數(shù)event.target.name選擇做些什么。

demo
class Reservation extends React.Component {
    constructor(props){
        super(props);
        this.state={
            isGoing:true,
            numberOfGuests:200
        }
        this.handleInputChange=this.handleInputChange.bind(this);
    }
    handleInputChange(event){
        const target = event.target;
        const value = target.type==='checkbox'?target.checked:target.value;
        const name = target.name;
        this.setState({
            [name]:value //es6語法
        })
    }
    render(){
        return(
            <form action="">
                <label htmlFor="">
                    is isGoing
                    <input type="text" name="isGoing" type="checkbox" 
                    checked={this.state.isGoing} onChange={this.handleInputChnage}/>
                </label>
                <br/>
                <label htmlFor="">
                    number of guests:
                    <input type="text" name="numberOfGuests" type="number" 
                    value={this.state.numberOfGuests} onChange={this.handleInputChange}/>
                </label>
            
            </form>
        )
    }
    
}

ReactDOM.render(
    <Reservation />,document.getElementById('root')
)

注意我們?nèi)绾问褂肊S6當(dāng)中的計算屬性名語法來更新與給定輸入名稱相對應(yīng)的狀態(tài)鍵:

this.setState({
  [name]: value
});
//相當(dāng)于ES5語法如下
var partialState = {};
partialState[name] = value;
this.setState(partialState);
6.受控組件的替代方法

有時使用受控組件可能很繁瑣,因?yàn)槟獮閿?shù)據(jù)可能發(fā)生變化的每一種方式都編寫一個事件處理程序,并通過一個組件來管理全部的狀態(tài)。當(dāng)您將預(yù)先存在的代碼庫轉(zhuǎn)換為React或?qū)eact應(yīng)用程序與非React庫集成時,這可能變得特別煩人。在以上情況下,你或許應(yīng)該看看非受控組件,這是一種表單的替代技術(shù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容