React—表單及事件處理

表單

提到React中表單及事件處理祝谚,就不得不先介紹一下控組件與非受控組件的概念。

在HTML中酣衷,表單元素與其他元素最大的不同是它自帶值或數(shù)據(jù)交惯,而且在我們的應(yīng)用中,只要是有表單出現(xiàn)的地方穿仪,就會(huì)有用戶輸入席爽,就會(huì)有表單事件觸發(fā),就會(huì)涉及的數(shù)據(jù)處理啊片。

在我們用React開發(fā)應(yīng)用時(shí)只锻,為了更好地管理應(yīng)用中的數(shù)據(jù),響應(yīng)用戶的輸入紫谷,編寫組件的時(shí)候呢齐饮,我們就會(huì)運(yùn)用到受控組件與非受控組件這兩個(gè)概念。

React推薦我們?cè)诮^大多數(shù)情況下都使用受控組件笤昨。這樣可以保證表單的數(shù)據(jù)在組件的state管理之下祖驱,而不是各自獨(dú)立保有各自的數(shù)據(jù)。

受控與非受控組件 Controlled & Uncontrolled

受控組件:

一般涉及到表單元素時(shí)我們才會(huì)使用這種分類方法瞒窒。受控組件的值由props或state傳入羹膳,用戶在元素上交互或輸入內(nèi)容會(huì)引起應(yīng)用state的改變。在state改變之后重新渲染組件根竿,我們才能在頁面中看到元素中值的變化陵像,假如組件沒有綁定事件處理函數(shù)改變state,用戶的輸入是不會(huì)起到任何效果的寇壳,這也就是“受控”的含義所在醒颖。

非受控組件:
類似于傳統(tǒng)的DOM表單控件,用戶輸入不會(huì)直接引起應(yīng)用state的變化壳炎,我們也不會(huì)直接為非受控組件傳入值泞歉。想要獲取非受控組件,我們需要使用一個(gè)特殊的ref屬性匿辩,同樣也可以使用defaultValue屬性來為其指定一次性的默認(rèn)值腰耙。

來看具體的例子:

// 受控組件
class ControlledInput extends React.Component {
  constructor() {
    super()
    this.state = {value: 'Please type here...'}
  }

  handleChange(event) {
    console.log('Controlled change:',event.target.value)
    this.setState({value: event.target.value})
  }

  render() {
    return (
      <label>
        Controlled Component:
        <input type="text"
               value={this.state.value}
               onChange={(e) => this.handleChange(e)}
        />
      </label>
    )
  }
}

// 非受控組件
class UncontrolledInput extends React.Component {
  constructor() {
    super()
  }

  handleChange() {
    console.log('Uncontrolled change:',this.input.value)
  }

  render() {
    return (
        <label>
          Uncontrolled Component:
          <input type="text"
                 defaultValue='Please type here...'
                 ref={(input) => this.input = input}
                 onChange={() =>this.handleChange()}
          />
        </label>
    )
  }
}

ReactDOM.render(
  <div>
    <UncontrolledInput />
    <ControlledInput />
  </div>
  ,document.getElementById('root'))

通常情況下,React當(dāng)中所有的表單控件都需要是受控組件铲球。但正如我們對(duì)受控組件的定義挺庞,想讓受控組件正常工作,每一個(gè)受控組件我們都需要為其編寫事件處理函數(shù)稼病,有的時(shí)候確實(shí)會(huì)很煩人选侨,比方說一個(gè)注冊(cè)表單你需要寫出所有驗(yàn)證姓名電話郵箱驗(yàn)證碼的邏輯,當(dāng)然也有一些小技巧可以讓同一個(gè)事件處理函數(shù)應(yīng)用在多個(gè)表單組件上然走,但生產(chǎn)開發(fā)中并沒有多大實(shí)際意義援制。更有可能我們是在對(duì)已有的項(xiàng)目進(jìn)行重構(gòu),除了React之外還有一些別的庫需要和表單交互芍瑞,這時(shí)候使用非受控組件可能會(huì)更方便一些晨仑。

表單元素

我們?cè)诮M件中聲明表單元素時(shí),一般都要為表單元素傳入應(yīng)用狀態(tài)中的值拆檬,可以通過state也可以通過props傳遞洪己,之后需要為其綁定相關(guān)事件,例如表單提交秩仆,輸入改變等码泛。在相關(guān)事件觸發(fā)的處理函數(shù)中,我們需要根據(jù)表單元素中用戶的輸入澄耍,對(duì)應(yīng)用數(shù)據(jù)進(jìn)行相應(yīng)的操作和改變噪珊,來看下面這個(gè)例子:

class ControlledInput extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      value: ""
    }
  }

  handleChange(event) {
    this.setState({
      value: event.target.value
      })
  }

  render() {
    return <input 
              type="text" 
              value={this.state.value} 
              onChange={ (e) => this.handleChange(e)} 
            />
  }
}

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

受控組件的輸入數(shù)據(jù)是一直和我們的應(yīng)用狀態(tài)綁定的,在上面這個(gè)例子中齐莲,事件處理函數(shù)中一定要有關(guān)state的更新操作痢站,這樣表單組件才能及時(shí)正確響應(yīng)用戶的輸入,可以把setState語句注釋掉來試驗(yàn)一下选酗。

textarea:

HTML

<textarea>
  Hello there, this is some text in a text area
</textarea>

JSX

<textarea value={this.state.value} onChange={this.handleChange} />

這里需要強(qiáng)調(diào)一下阵难,JSX中使用的和HTML標(biāo)簽同名的元素并不等同于原生的HTML標(biāo)簽,這只是React內(nèi)部抽象出來的一種標(biāo)簽的寫法芒填,只是看起來一樣而已呜叫,下面就介紹一下表單元素中空繁,JSX和HTML不一樣的,需要注意的地方朱庆。

在HTML中盛泡,textarea標(biāo)簽當(dāng)中的內(nèi)容都是在其開閉合標(biāo)簽之間的子節(jié)點(diǎn)當(dāng)中的。而在JSX中娱颊,為了統(tǒng)一傲诵,textarea也可以定義一個(gè)名為value的屬性,用來傳入應(yīng)用狀態(tài)中的相關(guān)值箱硕。

select

HTML

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

JSX

<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>

select也是一樣拴竹,注意這里的寫法,同樣我們可以為JSX當(dāng)中的select標(biāo)簽定義value屬性剧罩,與應(yīng)用狀態(tài)中相關(guān)數(shù)據(jù)值相同的option將會(huì)被默認(rèn)選中栓拜。

使用受控組件和非受控組件都是有響應(yīng)的適用場(chǎng)景的,就拿input來講斑响,比方說它是一個(gè)搜索框菱属,我們需要在應(yīng)用中實(shí)現(xiàn)根據(jù)搜索框內(nèi)容輸入異步返回相關(guān)搜索建議的功能,那么此處的input就應(yīng)該是受控組件舰罚。而假如它是Todo應(yīng)用中用來添加新事項(xiàng)的輸入框纽门,我們就沒有特別的理由需要實(shí)時(shí)獲取其中的數(shù)據(jù),只需要在添加事項(xiàng)的事件觸發(fā)時(shí)獲取輸入框中的值即可营罢,這個(gè)地方就可以使用非受控組件赏陵。

事件

HTML

<button onclick="activateLasers()">
Activate Lasers
</button>

JSX

<button onClick={activateLasers}>
Activate Lasers
</button>

React元素的事件屬性幾乎與HTML中的事件相關(guān)屬性相同,不過在React當(dāng)中饲漾,事件相關(guān)的屬性是以小駝峰的方式命名的蝙搔。在這里還是要強(qiáng)調(diào)一下,React元素中的事件處理也是React內(nèi)部的抽象封裝考传,這里只是說吃型,我們?cè)贘SX中寫出來,看上去差不多僚楞,并不代表這是HTML原生的事件屬性

// 手動(dòng)綁定
this.handleClick = this.handleClick.bind(this);
// 箭頭函數(shù)自動(dòng)綁定
handleClick = () => {
    console.log('this is:', this);
  }

新版本的React中勤晚,我們可以通過類和函數(shù)聲明React組件,在這兩種形式的聲明當(dāng)中泉褐,我們都可以為其定義事件處理函數(shù)赐写,函數(shù)定義的組件只需要在其方法內(nèi)部再定義事件觸發(fā)的函數(shù)即可;而如果是類聲明組件膜赃,類定義組件中的自定義方法默認(rèn)是沒有綁定this的挺邀,因此加入我們需要在事件處理函數(shù)中調(diào)用this.setState一類的方法,就必須要手動(dòng)將this綁定在相應(yīng)的事件處理函數(shù)上。

代碼示例:

class ControlledInput extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      value: ""
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({
      value: event.target.value
      })
  }

  render() {
    return <input 
              type="text" 
              value={this.state.value} 
              onChange={ this.handleChange} 
            />
  }
}

ReactDOM.render(<ControlledInput />,document.getElementById('root'))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末端铛,一起剝皮案震驚了整個(gè)濱河市泣矛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沦补,老刑警劉巖乳蓄,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異夕膀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)美侦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門产舞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人菠剩,你說我怎么就攤上這事易猫。” “怎么了具壮?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵准颓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我棺妓,道長(zhǎng)攘已,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任怜跑,我火速辦了婚禮样勃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘性芬。我一直安慰自己峡眶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布植锉。 她就那樣靜靜地躺著辫樱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俊庇。 梳的紋絲不亂的頭發(fā)上狮暑,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音暇赤,去河邊找鬼心例。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鞋囊,可吹牛的內(nèi)容都是我干的止后。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼译株!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起歉糜,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤乘寒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后伞辛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚤氏,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捏境,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年贰剥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蓬网,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锯厢,我是刑警寧澤捺氢,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布残黑,位于F島的核電站,受9級(jí)特大地震影響挤茄,放射性物質(zhì)發(fā)生泄漏踊沸。R本人自食惡果不足惜逼龟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一匀钧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧佑刷,春花似錦瘫絮、人聲如沸填硕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽藕甩。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讯榕,已是汗流浹背愚屁。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工霎槐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袭景,地道東北人闭树。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓榆纽,卻偏偏與公主長(zhǎng)得像鸵赫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狼忱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 本筆記基于React官方文檔灶泵,當(dāng)前React版本號(hào)為15.4.0惶洲。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,658評(píng)論 14 128
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南湃鹊,這只是我在學(xué)習(xí)過程中的一些閱讀筆記,個(gè)人覺得該教程講解深入淺出侨颈,比目前大...
    leonaxiong閱讀 2,813評(píng)論 1 18
  • 說在前面 關(guān)于 react 的總結(jié)過去半年就一直碎碎念著要搞起來扛拨,各(wo)種(tai)原(lan)因(le)渴频。心...
    陳嘻嘻啊閱讀 6,850評(píng)論 7 41
  • HTML模版 之后出現(xiàn)的React代碼嵌套入模版中拔第。 1. Hello world 這段代碼將一個(gè)一級(jí)標(biāo)題插入到指...
    ryanho84閱讀 6,221評(píng)論 0 9
  • 生活中的漂亮暂殖,才可愛
    取個(gè)帥氣的photo閱讀 72評(píng)論 0 0