17.React學(xué)習(xí)筆記.受控非受控組件

一. refs的使用##

React開發(fā)模式中擒贸,通常情況不需要橘沥,也不建議直接操作DOM元素窗轩,但是某些特殊的情況,確實需要獲取到DOM進行某些操作座咆。

  • 管理焦點痢艺,文本選擇/媒體播放;
  • 觸發(fā)強制動畫介陶;
  • 集成第三方DOM庫堤舒。
    如何創(chuàng)建refs來獲取對應(yīng)的DOM?三種方式哺呜。

1.1 創(chuàng)建方式

import React, { PureComponent, createRef } from 'react'
export default class App extends PureComponent {
  constructor(props) {
    super(props);
    // 方法二
    this.titleRef = createRef();
    // 方法三
    this.titleEl = null;
  }
  render() {
    return (
      <div>
        {/* <h2 ref="字符串/對象/回調(diào)函數(shù)">Hello World</h2> */}
        <h2 ref="titleRef">Hello React</h2>
        {/* 2. 目前React推薦的方式 */}
        <h2 ref={this.titleRef}>Hello React</h2>
        {/* 3.  */}
        <h2 ref={arg => { this.titleEl = arg }}>Hello React</h2>
        <button onClick={e => this.changeText()}>改變文本</button>
      </div>
    )
  }
  changeText() {
    // 1. 使用方式一:字符串(不推薦植酥,后續(xù)可能刪除)
    this.refs.titleRef.innerHTML = "Hello wwq"
    // 2. 使用對象(推薦)
    this.titleRef.current.innerHTML = "Hello wwq"
    // 3. 使用回調(diào)函數(shù)
    console.log(this.titleEl);
    this.titleEl.innerHTML = "Hello jsx3"
  }
}
  • 傳入字符串
    - 傳入一個對象,官方推薦弦牡,取的時候要導(dǎo)入createRef庫友驮,用其實例的current屬性。
  • 傳入回調(diào)函數(shù)

1.2 ref節(jié)點類型

  • ref用于html元素時驾锰,構(gòu)造函數(shù)中使用React.createRef()創(chuàng)建的ref接收底層DOM元素作為其current屬性卸留。

  • ref用于自定義class組件時,ref對象接收組件的掛載實例作為其current屬性椭豫。

  • 不能在函數(shù)組件上使用ref屬性耻瑟,因為他們沒有實例。

  • 但有時赏酥,我們想要獲取函數(shù)組件中的某個DOM元素喳整。

  • 這個時候我們可以通過React.forwardRef,之后學(xué)習(xí)hooks中使用refs裸扶。

二. 受控組件##

2.1 認識受控組件

  • 在React中框都,HTML表單的處理方式和普通的DOM元素不太一樣;表單元素通常會保存在一些內(nèi)部的state呵晨。
  • HTML中魏保,(input, textarea, select)之類的表單元素通常自己維護state熬尺,并根據(jù)用戶輸入進行更新。
  • 而在React中谓罗,可變狀態(tài)mutable state通常保存在組件的state屬性中粱哼,并且只能通過使用setState()來更新。
    • 我們將兩者結(jié)合起來檩咱,使React的state成為“唯一數(shù)據(jù)源”揭措;
    • 渲染表單的React組件還控制著用戶輸入過程中表單發(fā)生的操作;
    • React以這種方式控制取值的表單輸入元素就叫做“受控組件”刻蚯。

2.1.1 默認提交表單方式
2.2 常見表單的處理

  • 通過給form綁定onSubmit事件來更改默認行為绊含。
  • 給input綁定onChange事件來監(jiān)聽輸入變化。
  • 為了輸入框和state中數(shù)據(jù)保持一致芦倒,我們需要同步到value艺挪,單向數(shù)據(jù)流:input中輸入,觸發(fā)onChange -> onChange調(diào)用handleChange方法更新state -> state中的數(shù)據(jù)賦給input的value兵扬。
import React, { PureComponent } from 'react'
export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      username: "",
    }
  }
  render() {
    return (
      <div>
        <form onSubmit={e => this.handleSubmit(e)}>
          {/* label & htmlFor 聚焦 */}
          <label htmlFor="username">
            用戶:
            <input type="text"
              id="username"
              onChange={e => this.handleChange(e)}
              value={this.state.username}
            />
          </label>
          <input type="submit" value="提交" />
        </form>
      </div>
    )
  }
  handleSubmit(event) {
    event.preventDefault();
  }
  handleChange(event) {
    console.log(event.target.value);
    this.setState({
      username: event.target.value,
    })
  }
}
  • 如上綜合稱為受控組件麻裳,這時候只需要提交state中的數(shù)據(jù)即可。


    image.png

2.2.1 textarea標(biāo)簽

2.2.2 select標(biāo)簽

import React, { PureComponent } from 'react'
export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      fruits: "orange",
    }
  }
  render() {
    return (
      <div>
        <form onSubmit={e => this.handleSubmit(e)}>
          <select
            name="fruits"
            onChange={e => this.handleChange(e)}
            value={this.state.fruits}>
            <option value="apple">蘋果</option>
            <option value="banana">香蕉</option>
            <option value="orange">橘子</option>
          </select>
          <input type="submit" value="提交" />
        </form>
      </div>
    )
  }
  handleSubmit(event) {
    event.preventDefault();
    console.log(this.state.fruits);
  }
  handleChange(event) {
    console.log(event.target.value);
    this.setState({
      fruits: event.target.value,
    })
  }
}

2.2.3 處理多個輸入

import React, { PureComponent } from 'react'

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      username: "",
      password: "",
      valid: "",
    }
  }
  render() {
    return (
      <div>
        <form onSubmit={e => this.handleSubmit(e)}>
          {/* label & htmlFor 聚焦 */}
          <label htmlFor="username">
            用戶:
            <input type="text"
              id="username"
              name="username"
              onChange={e => this.handleChange(e)}
              value={this.state.username}
            />
          </label>
          <br />
          <label htmlFor="password">
            密碼:
            <input type="text"
              id="password"
              name="password"
              onChange={e => this.handleChange(e)}
              value={this.state.password}
            />
          </label>
          <br />
          <label htmlFor="valid">
            驗證:
            <input type="text"
              id="valid"
              name="valid"
              onChange={e => this.handleChange(e)}
              value={this.state.valid}
            />
          </label>

          <input type="submit" value="提交" />
        </form>
      </div>
    )
  }
  handleSubmit(event) {
    event.preventDefault();
    const {username,password,valid} = this.state;
    console.log(username,password,valid);
  }
  handleChange(event) {
    // 計算屬性名
    this.setState({
      [event.target.name]: event.target.value,
    })
  }
}

三. 非受控組件 (不推薦)

  • 推薦:大多數(shù)情況使用受控組件器钟。
  • 一個受控組件中津坑,表單數(shù)據(jù)是有React組件來管理的;
  • 另一種方式是非受控組件傲霸,這時表單數(shù)據(jù)將交由DOM節(jié)點來處理疆瑰;
  • 非受控組件中,通過ref來從DOM節(jié)點中獲取表單數(shù)據(jù)昙啄。
import React, { PureComponent,createRef } from 'react'
export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.usernameRef = createRef();
  }
  render() {
    return (
      <div>
        <form onSubmit={e => this.handleSubmit(e)}>
          <label htmlFor="username">
            用戶:
            <input type="text" id="username" ref={this.usernameRef}/>
          </label>
          <input type="submit" value="提交" />
        </form>
      </div>
    )
  }
  handleSubmit(event) {
    event.preventDefault();
    console.log(this.usernameRef.current.value);
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末穆役,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子梳凛,更是在濱河造成了極大的恐慌耿币,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件韧拒,死亡現(xiàn)場離奇詭異淹接,居然都是意外死亡,警方通過查閱死者的電腦和手機叛溢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門塑悼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人楷掉,你說我怎么就攤上這事厢蒜。” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵郭怪,是天一觀的道長支示。 經(jīng)常有香客問我刊橘,道長鄙才,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任促绵,我火速辦了婚禮攒庵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘败晴。我一直安慰自己浓冒,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布尖坤。 她就那樣靜靜地躺著稳懒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慢味。 梳的紋絲不亂的頭發(fā)上场梆,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音纯路,去河邊找鬼或油。 笑死,一個胖子當(dāng)著我的面吹牛驰唬,可吹牛的內(nèi)容都是我干的顶岸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼叫编,長吁一口氣:“原來是場噩夢啊……” “哼辖佣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起搓逾,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卷谈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后恃逻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雏搂,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年寇损,在試婚紗的時候發(fā)現(xiàn)自己被綠了凸郑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡矛市,死狀恐怖芙沥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤而昨,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布救氯,位于F島的核電站,受9級特大地震影響歌憨,放射性物質(zhì)發(fā)生泄漏着憨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一务嫡、第九天 我趴在偏房一處隱蔽的房頂上張望甲抖。 院中可真熱鬧,春花似錦心铃、人聲如沸准谚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柱衔。三九已至,卻和暖如春愉棱,著一層夾襖步出監(jiān)牢的瞬間唆铐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工羽氮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留或链,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓档押,卻偏偏與公主長得像澳盐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子令宿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355