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