摘要:函數(shù)更新屬性,進(jìn)而更新元素的值。由于箭頭函數(shù)存在于父組件中,所以中的指向父組件。一旦表單被提交,的值就被設(shè)置為。遺憾的是,沒(méi)有節(jié)點(diǎn)是包含了集合的。在這種情況下,這個(gè)節(jié)點(diǎn)列表包含三個(gè)節(jié)點(diǎn)和被選中的值。
原文地址:React Forms: Using Refs
原文作者:Loren Stewart
譯者:萌萌
校對(duì)者:小 boy
React 提供了兩種從 元素中獲取值的標(biāo)準(zhǔn)方法。第一種方法是實(shí)現(xiàn)所謂的受控組件 (可以看我博客里發(fā)表的文章) ,第二種方法是使用 React 的 ref 屬性。
受控組件很重,被展示的值和組件的 state 綁定是它的特性。我們通過(guò)執(zhí)行一個(gè)附著在 form 元素上的 onChange 事件句柄,來(lái)更新被展示的值。onChange 函數(shù)更新 state 屬性,進(jìn)而更新 form 元素的值。
(在看到下面的文章之前,如果你只是想看相應(yīng)的示例代碼:請(qǐng)移步這里)
受控組件示例:
import React, { Component } from "react"; class ControlledCompExample extends Component { constructor() { super(); this.state = { fullName: "" } } handleFullNameChange = (e) => { this.setState({ fullName: e.target.value }) } handleSubmit = (e) => { e.preventDefault(); console.log(this.state.fullName) } render() { return (); } } export default ControlledCompExample;
input 的值是 this.state.fullName (在第7行和第26行)。 onChange 函數(shù)是 handleFullNameChange (第 10 - 14 行和第 27 行)。
受控組件最主要的優(yōu)勢(shì)是:
1、便于驗(yàn)證用戶的輸入
2、可以根據(jù)受控組件的值動(dòng)態(tài)地渲染其他組件。例如:一個(gè)用戶在下拉列表中選擇的值(如“dog” 或者 “cat” )可以控制在 form 中渲染的其他 form 組件(例如:一個(gè)設(shè)置品種的復(fù)選框)
受控組件的缺點(diǎn)是要寫(xiě)大量的代碼。你需要通過(guò) props 把 state 屬性傳遞給 form 元素,還需要一個(gè)函數(shù)來(lái)更新這個(gè)屬性的值。
對(duì)于單一表單元素來(lái)說(shuō)這真的不是什么問(wèn)題 —— 但是如果你需要一個(gè)龐大并且復(fù)雜的表單(不需要?jiǎng)討B(tài)渲染或者實(shí)時(shí)驗(yàn)證),過(guò)度使用受控表單會(huì)讓你書(shū)寫(xiě)成噸的代碼。
從 form 元素取值的簡(jiǎn)便的方法是使用 ref 屬性。我們用不同的方式來(lái)應(yīng)對(duì)不同的 form 元素和組件結(jié)構(gòu),所以這篇文章剩下的內(nèi)容分為以下幾個(gè)部分。
文本輸入框、數(shù)字輸入框和選擇框
子組件通過(guò) props 傳值給父組件
Radio 標(biāo)簽集合
Checkbox 標(biāo)簽集合
1、文本輸入框、數(shù)字輸入框和選擇框使用 ref 的最簡(jiǎn)單的例子是文本和數(shù)字 input 元素。我們?cè)?input 的 ref 屬性里添加一個(gè)把 input 本身作為參數(shù)的箭頭函數(shù)。我喜歡把參數(shù)命名為和元素本身一樣的的名字,就像下面的第三行那個(gè)樣子:
this.fullName = input} />
由于該參數(shù)是 input 元素本身的別名,你可以隨心所欲地為它命名:
this.amount = cashMoney} />
接著你可以拿到該參數(shù),并將它賦值給當(dāng)前 class 內(nèi) this 關(guān)鍵字上掛載的屬性(譯者注:這里的 class 指的是 JSX 所處的 React 組件 class)。input(例如: DOM 節(jié)點(diǎn))可以通過(guò) this.fullName 和 this.amount 來(lái)讀取。它的值可以通過(guò) this.fullName.value 和 this.amount.value 來(lái)讀取。
選擇元素也可以用相同的方法(例如:下拉列表)。
選擇元素的值可以通過(guò) this.petType.value 獲取。
2、子組件通過(guò) props 傳值給父組件通過(guò)受控組件,父組件獲取子組件的值十分簡(jiǎn)單 —— 父組件中已經(jīng)有這個(gè)值了(譯者注:在父組件中定義)!它被傳遞給子組件。同時(shí) onChange 方法也被傳給子組件,用戶通過(guò)與 UI 互動(dòng)(譯者注:觸發(fā) onChange)來(lái)更新該值。
你可以在我上篇文章的受控組件示例中看到它是如何運(yùn)行的。
雖然該值已經(jīng)存在于受控組件的父組件中,但是當(dāng)使用 ref 的時(shí)候卻不是這樣。使用 ref 的時(shí)候,該值存在于 DOM 節(jié)點(diǎn)自身當(dāng)中,必須向上與父組件通信。
要將該值從子組件傳給父組件,父組件需要向子組件傳遞一個(gè) 鉤子 。然后子組件將節(jié)點(diǎn)掛載到 鉤子 上, 以便父組件讀取。
在我們更深入的探討之前先來(lái)看一些代碼。
import React, { Component } from "react"; class RefsForm extends Component { handleSubmit = (e) => { e.preventDefault(); console.log("first name:", this.firstName.value); this.firstName.value = "Got ya!"; } render() { return (); } } function CustomInput(props) { return (); } export default RefsForm;
通過(guò)上面的代碼,可以看到一個(gè) form 組件 RefForm 和一個(gè)叫做 CustomInput 的 input 組件。通常,箭頭函數(shù)都是在 input 自身上面,但是從這(15 - 27 行)可以看到它是通過(guò) props 傳遞的。由于箭頭函數(shù)存在于父組件中,所以 this.firstName 中的 this 指向父組件。
input 子組件的值被賦給父組件的 this.firstName 屬性,所以父組件可以獲得子組件的值?,F(xiàn)在,父組件中的 this.firstName 指的是子組件中的 DOM 節(jié)點(diǎn)(例如: CustomInput 中的 input)。
父組件不僅可以訪問(wèn) input 中的 DOM 節(jié)點(diǎn),還可以在父組件內(nèi)給節(jié)點(diǎn)的值賦值。在上文的第 7 行可以看到例子。一旦表單被提交, input 的值就被設(shè)置為 “Got ya!” 。
這種方式有點(diǎn)讓人摸不著頭腦,所以請(qǐng)仔細(xì)揣摩并敲代碼實(shí)踐一下,直至完全理解。
你可能會(huì)寫(xiě)出來(lái)更好的 radio 和 checkbox 受控組件,但是如果你真的想要用 `ref` ,那么接下來(lái)的兩部分會(huì)幫到你。3、 Radio 標(biāo)簽集合
不像 text 和 number 這類(lèi) input 元素,radio 元素是成組出現(xiàn)的。每組中的元素都有相同的 name 屬性,就像這樣:
在 “pet” radio 標(biāo)簽集合中有三個(gè)選項(xiàng) —— “cat”、“dog” 和 “ferret”。
由于我們關(guān)心的是整個(gè)集合的元素,所以給每個(gè)單選框設(shè)置 ref 并不是一個(gè)好主意。遺憾的是,沒(méi)有 DOM 節(jié)點(diǎn)是包含了 radio 集合的。
可以通過(guò)下面的三步來(lái)檢索出 radio 集合的值:
1、在 form 標(biāo)簽上設(shè)置 ref (下面的第20行)。
2、從 form 中取出這個(gè) radio 集合。然后它應(yīng)該是 pet 集合(下面的第9行)。
此處返回一個(gè)節(jié)點(diǎn)列表和一個(gè)值。在這種情況下,這個(gè)節(jié)點(diǎn)列表包含三個(gè) input 節(jié)點(diǎn)和被選中的值。
需要注意的是這個(gè)節(jié)點(diǎn)列表是個(gè)類(lèi)數(shù)組,它沒(méi)有數(shù)組的方法。在下一部分中還有更多關(guān)于這個(gè)話題的內(nèi)容。
3、使用 . 方法來(lái)獲取這個(gè)集合的值(下面的第13行)。
import React, { Component } from "react"; class RefsForm extends Component { handleSubmit = (e) => { e.preventDefault(); // 從 form 中取出節(jié)點(diǎn)列表 // 它是一個(gè)類(lèi)數(shù)組,沒(méi)有數(shù)組的方法 const { pet } = this.form; // radio 標(biāo)簽集合有 value 屬性 // 查看打印出來(lái)的數(shù)據(jù) console.log(pet, pet.value); } render() { return (); } } export default RefsForm;
如果你正在用子組件寫(xiě)一個(gè)表單也是可行的。盡管組件中會(huì)有更多的邏輯,但是從 radio 集合中獲取值的方法是不變的。
import React, { Component } from "react"; class RefsForm extends Component { handleSubmit = (e) => { e.preventDefault(); // 從 form 中取出節(jié)點(diǎn)列表 // 它是一個(gè)類(lèi)數(shù)組,沒(méi)有數(shù)組的方法 const { pet } = this.form; // radio 標(biāo)簽集合有 value 屬性 // 查看打印出來(lái)的數(shù)據(jù) console.log(pet, pet.value); } render() { return (4、 Checkbox 標(biāo)簽集合); } } function RadioSet(props) { return ({props.setOptions.map(option => { return ( ) })}); } export default RefsForm;
和 radio 標(biāo)簽集合不一樣, Checkbox 標(biāo)簽集合可能有多個(gè)值。導(dǎo)致獲取這些值會(huì)比獲取 radio 標(biāo)簽集合的值難一些。
可以通過(guò)下面的五步來(lái)檢索出 checkbox 標(biāo)簽集合被選中的值:
1、在 form 標(biāo)簽上設(shè)置 ref (下面的第27行)。
2、從 form 中取出這個(gè)checkbox 集合。然后它應(yīng)該是 pet 集合(第9行)。
此處返回一個(gè)節(jié)點(diǎn)列表和一個(gè)值
需要注意的是這個(gè)節(jié)點(diǎn)列表是一個(gè)類(lèi)數(shù)組,它沒(méi)有數(shù)組的方法,然后我們就需要進(jìn)行下面的這一步 ...
3、把這個(gè)節(jié)點(diǎn)列表轉(zhuǎn)換成一個(gè)數(shù)組,然后就可以使用數(shù)組的方法了(第 12 行的 checkboxArray )。
4、使用 Array.filter() 獲取選中的 checkbox (第 15 行的 checkedCheckboxes )。
5、使用 Array.map() 獲取選中的 checkbox 的唯一的值(第 19 行的 checkedCheckboxesValues )
import React, { Component } from "react"; class RefsForm extends Component { handleSubmit = (e) => { e.preventDefault(); // 從 form 中取出節(jié)點(diǎn)列表 // 它是一個(gè)類(lèi)數(shù)組,沒(méi)有數(shù)組的方法 const { pet } = this.form; // 把節(jié)點(diǎn)列表轉(zhuǎn)換成一個(gè)數(shù)組 const checkboxArray = Array.prototype.slice.call(pet); // 僅取出被選中的 checkbox const checkedCheckboxes = checkboxArray.filter(input => input.checked); console.log("checked array:", checkedCheckboxes); // 使用 .map() 方法從每個(gè)被選中的 checkbox 中把值取出來(lái) const checkedCheckboxesValues = checkedCheckboxes.map(input => input.value); console.log("checked array values:", checkedCheckboxesValues); } render() { return (); } } export default RefsForm;
使用子組件寫(xiě) checkbox 的方法和上一部分中寫(xiě) radio 的方法是一樣的。
import React, { Component } from "react"; class RefsForm extends Component { handleSubmit = (e) => { e.preventDefault(); // 從 form 中取出節(jié)點(diǎn)列表 // 它是一個(gè)類(lèi)數(shù)組,沒(méi)有數(shù)組的方法 const { pet } = this.form; // 把節(jié)點(diǎn)列表轉(zhuǎn)換成一個(gè)數(shù)組 const checkboxArray = Array.prototype.slice.call(pet); // 僅取出被選中的 checkbox const checkedCheckboxes = checkboxArray.filter(input => input.checked); console.log("checked array:", checkedCheckboxes); // 使用 .map() 方法從每個(gè)被選中的 checkbox 中把值取出來(lái) const checkedCheckboxesValues = checkedCheckboxes.map(input => input.value); console.log("checked array values:", checkedCheckboxesValues); } render() { return (結(jié)論); } } function CheckboxSet(props) { return ({props.setOptions.map(option => { return ( ) })}); } export default RefsForm;
如果你不需要:
1、實(shí)時(shí)監(jiān)視 form 元素的值(例如:為了基于用戶的輸入渲染之后的組件)
2、實(shí)時(shí)執(zhí)行自定義驗(yàn)證方法
那么使用 ref 方法獲取 form 元素的值是一個(gè)很好的方法。
大多數(shù)情況下,越過(guò)受控組件使用 ref 最主要的價(jià)值是會(huì)寫(xiě)更少的代碼。 checkbox ( radio 其次)是一個(gè)特例。對(duì)于 checkbox ,使用 ref 省下的代碼量是很少的,所以無(wú)法說(shuō)是使用受控組件好還是 ref 好。
iKcamp原創(chuàng)新書(shū)《移動(dòng)Web前端高效開(kāi)發(fā)實(shí)戰(zhàn)》已在亞馬遜、京東、當(dāng)當(dāng)開(kāi)售。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/85076.html
摘要:受控輸入框只會(huì)顯示通過(guò)傳入的數(shù)據(jù)。例如,數(shù)組中的元素將會(huì)渲染三個(gè)單選框或復(fù)選框。屬性接收一個(gè)布爾值,用來(lái)表示組件是否應(yīng)該被渲染成選中狀態(tài)。 原文地址:React.js Forms: Controlled Components 原文作者:Loren Stewart 譯者:小 B0Y 校對(duì)者:珂珂君 本文涵蓋以下受控組件: 文本輸入框 數(shù)字輸入框 單選框 復(fù)選框 文本域 下拉...
摘要:通過(guò)表單添加任務(wù)在這個(gè)步驟,我們將為用戶在列表上添加輸入框。在中,這是一種監(jiān)聽(tīng)瀏覽器事件的方式,就像是在表單上有提交事件一樣。這對(duì)一個(gè)任務(wù)列表來(lái)說(shuō)并不是非常好。在下一步,我們將給待辦事宜的列表添加一個(gè)非常重要的功能已完成功能和刪除功能 通過(guò)表單(form)添加任務(wù) 在這個(gè)步驟,我們將為用戶在列表上添加輸入框。 首先,在App.jsx文件中App組件上添加表單吧。 Tod...
摘要:前端日?qǐng)?bào)精選我是如何實(shí)現(xiàn)的在線升級(jí)熱更新功能的張?chǎng)涡聆慰臻g鑫生活翻譯表單的運(yùn)用第期晉升評(píng)審的套路異步編程的四種方式黃博客精選組件設(shè)計(jì)和分解思考掘金中文譯使登錄頁(yè)面變得正確掘金前端從強(qiáng)制開(kāi)啟壓縮探究插件運(yùn)行機(jī)制掘金個(gè)常用的簡(jiǎn) 2017-06-28 前端日?qǐng)?bào) 精選 我是如何實(shí)現(xiàn)electron的在線升級(jí)熱更新功能的? ? 張?chǎng)涡?鑫空間-鑫生活【翻譯】React 表單: Refs 的運(yùn)用【...
摘要:系列系列簡(jiǎn)單模擬語(yǔ)法一系列合成事件與二系列算法實(shí)現(xiàn)分析三系列從到再到四系列與部分源碼解析五系列從使用了解的各種使用方案六的誕生他是的一種擴(kuò)展語(yǔ)法。這個(gè)函數(shù)接受組件的實(shí)例或元素作為參數(shù),以存儲(chǔ)它們并使它們能被其他地方訪問(wèn)。 React系列 React系列 --- 簡(jiǎn)單模擬語(yǔ)法(一)React系列 --- Jsx, 合成事件與Refs(二)React系列 --- virtualdom di...
摘要:希望大家在這浮夸的前端圈里,保持冷靜,堅(jiān)持每天花分鐘來(lái)學(xué)習(xí)與思考。 今天的React題沒(méi)有太多的故事…… 半個(gè)月前出了248個(gè)Vue的知識(shí)點(diǎn),受到很多朋友的關(guān)注,都強(qiáng)烈要求再出多些React相前的面試題,受到大家的邀請(qǐng),我又找了20多個(gè)React的使用者,他們給出了328道React的面試題,由我整理好發(fā)給大家,同時(shí)發(fā)布在了前端面試每日3+1的React專(zhuān)題,希望對(duì)大家有所幫助,同時(shí)大...
閱讀 2326·2019-08-30 15:54
閱讀 2047·2019-08-30 13:49
閱讀 730·2019-08-29 18:44
閱讀 885·2019-08-29 18:39
閱讀 1171·2019-08-29 15:40
閱讀 1590·2019-08-29 12:56
閱讀 3217·2019-08-26 11:39
閱讀 3161·2019-08-26 11:37