React中如何實(shí)現(xiàn)受控組件與非受控組件
啥是 React 里的受控組件和非受控組件
在 React 開發(fā)里,組件可分為受控組件和非受控組件,它們處理表單數(shù)據(jù)的方式各有不同。接下來咱就用通俗易懂的大白話詳細(xì)說說它們的實(shí)現(xiàn)原理、方法、區(qū)別、作用和應(yīng)用場景。
受控組件
受控組件就像是一個(gè)被人緊緊牽著線的風(fēng)箏,它的數(shù)據(jù)完全由 React 組件來控制。也就是說,表單元素的值是由 React 組件的狀態(tài)來決定的,表單元素的任何變化都會(huì)觸發(fā) React 組件的狀態(tài)更新。
以下是一個(gè)簡單的受控組件示例:
import React, { useState } from 'react'; // 定義一個(gè)名為 ControlledInput 的函數(shù)組件 function ControlledInput() { // 使用 useState 鉤子創(chuàng)建一個(gè)名為 value 的狀態(tài)變量,初始值為空字符串 const [value, setValue] = useState(''); // 定義一個(gè)名為 handleChange 的函數(shù),用于處理輸入框的值變化事件 const handleChange = (event) => { // 通過 event.target.value 獲取輸入框的最新值,并使用 setValue 更新狀態(tài) setValue(event.target.value); }; // 渲染一個(gè)輸入框,將 value 狀態(tài)綁定到輸入框的 value 屬性上 // 當(dāng)輸入框的值發(fā)生變化時(shí),調(diào)用 handleChange 函數(shù)更新狀態(tài) return ( <div> <input type="text" value={value} onChange={handleChange} /> <p>你輸入的內(nèi)容是: {value}</p> </div> ); } export default ControlledInput;
實(shí)現(xiàn)原理
受控組件的實(shí)現(xiàn)原理基于 React 的單向數(shù)據(jù)流。表單元素的值由 React 組件的狀態(tài)來控制,當(dāng)表單元素的值發(fā)生變化時(shí),會(huì)觸發(fā)一個(gè)事件處理函數(shù),在這個(gè)函數(shù)里更新組件的狀態(tài),從而更新表單元素的值。
方法
用 useState 鉤子或者類組件的 this.state 來創(chuàng)建一個(gè)狀態(tài)變量,用于存放表單元素的值。
把狀態(tài)變量綁定到表單元素的 value 屬性上。
給表單元素添加一個(gè) onChange 事件處理函數(shù),在函數(shù)里更新狀態(tài)變量。
作用和應(yīng)用場景
受控組件適合需要實(shí)時(shí)驗(yàn)證用戶輸入、根據(jù)用戶輸入動(dòng)態(tài)更新 UI 或者與其他組件共享表單數(shù)據(jù)的場景。比如登錄表單、搜索框等。
非受控組件
非受控組件就像是一只自由飛翔的鳥,它的數(shù)據(jù)由 DOM 自己來管理。也就是說,表單元素的值是由 DOM 來維護(hù)的,React 組件只能在需要的時(shí)候從 DOM 里獲取表單元素的值。
下面是一個(gè)簡單的非受控組件示例:
import React, { useRef } from 'react'; // 定義一個(gè)名為 UncontrolledInput 的函數(shù)組件 function UncontrolledInput() { // 使用 useRef 鉤子創(chuàng)建一個(gè)名為 inputRef 的引用對象 const inputRef = useRef(null); // 定義一個(gè)名為 handleSubmit 的函數(shù),用于處理表單提交事件 const handleSubmit = (event) => { // 阻止表單的默認(rèn)提交行為 event.preventDefault(); // 通過 inputRef.current.value 獲取輸入框的值 const value = inputRef.current.value; // 打印輸入框的值 console.log('你輸入的內(nèi)容是:', value); }; // 渲染一個(gè)表單,包含一個(gè)輸入框和一個(gè)提交按鈕 // 將 inputRef 引用對象綁定到輸入框的 ref 屬性上 // 當(dāng)表單提交時(shí),調(diào)用 handleSubmit 函數(shù) return ( <form onSubmit={handleSubmit}> <input type="text" ref={inputRef} /> <button type="submit">提交</button> </form> ); } export default UncontrolledInput;
實(shí)現(xiàn)原理
非受控組件的實(shí)現(xiàn)原理是借助 React 的 ref 來訪問 DOM 元素。通過 ref 可以直接獲取 DOM 元素的屬性和方法,從而在需要的時(shí)候獲取表單元素的值。
方法
用 useRef 鉤子或者類組件的 createRef 方法創(chuàng)建一個(gè) ref 對象。
把 ref 對象綁定到表單元素的 ref 屬性上。
在需要的時(shí)候,通過 ref 對象的 current 屬性來訪問 DOM 元素,進(jìn)而獲取表單元素的值。
作用和應(yīng)用場景
非受控組件適合那些只需要在表單提交時(shí)獲取表單數(shù)據(jù),或者與第三方庫集成的場景。比如文件上傳表單、簡單的表單提交等。
區(qū)別
- 數(shù)據(jù)控制:受控組件的數(shù)據(jù)由 React 組件的狀態(tài)控制,非受控組件的數(shù)據(jù)由 DOM 自己管理。
- 事件處理:受控組件需要為表單元素添加 onChange 事件處理函數(shù)來更新狀態(tài),非受控組件不需要處理表單元素的值變化事件。
- 數(shù)據(jù)獲?。菏芸亟M件可以隨時(shí)獲取表單元素的值,非受控組件只能在需要的時(shí)候通過 ref 來獲取表單元素的值。
綜上所述,受控組件和非受控組件各有優(yōu)劣,你要根據(jù)具體的需求來選擇合適的組件類型。
受控組件和非受控組件適用場景
在React中,受控組件和非受控組件分別適用于哪些場景?
在 React 里,受控組件和非受控組件各有特點(diǎn),適用于不同的應(yīng)用場景,下面為你詳細(xì)介紹:
受控組件適用場景
1. 實(shí)時(shí)驗(yàn)證用戶輸入
當(dāng)你需要對用戶輸入的數(shù)據(jù)進(jìn)行實(shí)時(shí)驗(yàn)證時(shí),受控組件是很好的選擇。因?yàn)槭芸亟M件可以在每次輸入變化時(shí)觸發(fā)狀態(tài)更新,從而能及時(shí)對輸入內(nèi)容進(jìn)行檢查。
比如,在一個(gè)注冊表單里,要求用戶輸入的密碼長度至少為 6 位,一旦用戶輸入的內(nèi)容發(fā)生變化,就可以立即檢查密碼長度是否符合要求,并給出相應(yīng)提示。
import React, { useState } from 'react'; function PasswordInput() { const [password, setPassword] = useState(''); const [error, setError] = useState(''); const handleChange = (e) => { const newPassword = e.target.value; setPassword(newPassword); if (newPassword.length < 6) { setError('密碼長度至少為 6 位'); } else { setError(''); } }; return ( <div> <input type="password" value={password} onChange={handleChange} /> {error && <p style={{ color: 'red' }}>{error}</p>} </div> ); } export default PasswordInput;
2. 根據(jù)輸入動(dòng)態(tài)更新 UI
如果需要根據(jù)用戶的輸入動(dòng)態(tài)更新頁面的其他部分,受控組件可以方便地實(shí)現(xiàn)這一功能。因?yàn)榻M件狀態(tài)的變化可以直接反映到 UI 上。
例如,一個(gè)搜索框,用戶輸入關(guān)鍵詞后,頁面上會(huì)實(shí)時(shí)顯示與關(guān)鍵詞匹配的搜索結(jié)果。
import React, { useState } from 'react'; const data = ['apple', 'banana', 'cherry', 'date']; function SearchInput() { const [searchTerm, setSearchTerm] = useState(''); const handleChange = (e) => { setSearchTerm(e.target.value); }; const filteredData = data.filter(item => item.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( <div> <input type="text" value={searchTerm} onChange={handleChange} placeholder="搜索..." /> <ul> {filteredData.map(item => ( <li key={item}>{item}</li> ))} </ul> </div> ); } export default SearchInput;
3. 多表單元素聯(lián)動(dòng)
當(dāng)多個(gè)表單元素之間存在聯(lián)動(dòng)關(guān)系時(shí),受控組件可以更好地管理它們之間的數(shù)據(jù)交互。通過更新狀態(tài),可以同時(shí)更新多個(gè)表單元素的值。
例如,一個(gè)包含省份和城市選擇的表單,當(dāng)用戶選擇不同的省份時(shí),城市下拉列表會(huì)相應(yīng)地更新。
import React, { useState } from 'react'; const provinceCityMap = { '廣東': ['廣州', '深圳', '珠海'], '江蘇': ['南京', '蘇州', '無錫'] }; function ProvinceCitySelector() { const [province, setProvince] = useState(''); const [city, setCity] = useState(''); const handleProvinceChange = (e) => { const newProvince = e.target.value; setProvince(newProvince); setCity(''); }; const handleCityChange = (e) => { setCity(e.target.value); }; return ( <div> <select value={province} onChange={handleProvinceChange}> <option value="">請選擇省份</option> {Object.keys(provinceCityMap).map(p => ( <option key={p} value={p}>{p}</option> ))} </select> <select value={city} onChange={handleCityChange} disabled={!province}> <option value="">請選擇城市</option> {province && provinceCityMap[province].map(c => ( <option key={c} value={c}>{c}</option> ))} </select> </div> ); } export default ProvinceCitySelector;
非受控組件適用場景
1. 簡單表單提交
在一些簡單的表單場景中,只需要在表單提交時(shí)獲取表單數(shù)據(jù),而不需要實(shí)時(shí)跟蹤輸入變化,非受控組件可以減少代碼復(fù)雜度。
例如,一個(gè)簡單的留言表單,用戶填寫完內(nèi)容后點(diǎn)擊提交按鈕,將數(shù)據(jù)發(fā)送到服務(wù)器。
import React, { useRef } from 'react'; function MessageForm() { const messageRef = useRef(null); const handleSubmit = (e) => { e.preventDefault(); const message = messageRef.current.value; console.log('留言內(nèi)容:', message); }; return ( <form onSubmit={handleSubmit}> <textarea ref={messageRef} /> <button type="submit">提交留言</button> </form> ); } export default MessageForm;
2. 與第三方庫集成
當(dāng)需要與一些第三方表單庫或插件集成時(shí),非受控組件可以更方便地與這些庫進(jìn)行交互。因?yàn)榈谌綆焱ǔJ腔?DOM 操作的,使用 ref 可以直接訪問 DOM 元素。
例如,使用一個(gè)第三方的富文本編輯器,通過 ref 可以方便地獲取編輯器中的內(nèi)容。
import React, { useRef, useEffect } from 'react'; // 假設(shè)這是一個(gè)第三方富文本編輯器庫 import RichTextEditor from 'some-rich-text-editor-library'; function RichTextInput() { const editorRef = useRef(null); useEffect(() => { const editor = new RichTextEditor(editorRef.current); // 可以在這里進(jìn)行更多的編輯器初始化配置 }, []); const handleSubmit = (e) => { e.preventDefault(); const content = editorRef.current.getValue(); console.log('富文本內(nèi)容:', content); }; return ( <form onSubmit={handleSubmit}> <div ref={editorRef} /> <button type="submit">提交內(nèi)容</button> </form> ); } export default RichTextInput;
3. 文件上傳
在文件上傳場景中,使用非受控組件可以更方便地獲取用戶選擇的文件。因?yàn)槲募斎肟虻闹挡荒芡ㄟ^狀態(tài)來控制,使用 ref 可以直接訪問文件輸入框的 files 屬性。
import React, { useRef } from 'react'; function FileUpload() { const fileInputRef = useRef(null); const handleSubmit = (e) => { e.preventDefault(); const file = fileInputRef.current.files[0]; if (file) { console.log('選擇的文件:', file.name); } }; return ( <form onSubmit={handleSubmit}> <input type="file" ref={fileInputRef} /> <button type="submit">上傳文件</button> </form> ); } export default FileUpload;
React vue受控組件與非受控組件區(qū)別
那么,與vue受控組件和非受控組件的區(qū)別
整體概念差異不大,但實(shí)現(xiàn)方式有別
在 React 和 Vue 中,受控組件和非受控組件的核心概念類似,但在具體實(shí)現(xiàn)、語法和使用習(xí)慣上存在明顯差異。
受控組件
React 受控組件
在 React 里,受控組件的數(shù)據(jù)完全由 React 組件的狀態(tài)控制。表單元素的值取決于狀態(tài),并且任何變化都會(huì)觸發(fā)狀態(tài)更新。
import React, { useState } from 'react'; function ReactControlledInput() { // 創(chuàng)建一個(gè)狀態(tài)變量來存儲(chǔ)輸入框的值,初始為空 const [value, setValue] = useState(''); // 處理輸入框變化的函數(shù) const handleChange = (e) => { // 更新狀態(tài)變量 setValue(e.target.value); }; return ( <div> {/* 輸入框的值綁定到狀態(tài)變量,變化時(shí)觸發(fā) handleChange 函數(shù) */} <input type="text" value={value} onChange={handleChange} /> <p>輸入內(nèi)容: {value}</p> </div> ); } export default ReactControlledInput;
Vue 受控組件
在 Vue 中,受控組件通常使用 v-model 指令來實(shí)現(xiàn)雙向數(shù)據(jù)綁定。v-model 是一個(gè)語法糖,它結(jié)合了 :value 和 @input 事件。
<template> <div> <!-- 使用 v-model 實(shí)現(xiàn)雙向數(shù)據(jù)綁定 --> <input v-model="value" /> <p>輸入內(nèi)容: {{ value }}</p> </div> </template> ???????<script> export default { data() { // 定義一個(gè)數(shù)據(jù)屬性來存儲(chǔ)輸入框的值,初始為空 return { value: '' }; } }; </script>
區(qū)別總結(jié)
- 語法方面:React 需手動(dòng)綁定 value 屬性和 onChange 事件處理函數(shù),而 Vue 用 v-model 指令就能實(shí)現(xiàn)雙向數(shù)據(jù)綁定,語法更簡潔。
- 數(shù)據(jù)流向:React 是單向數(shù)據(jù)流,通過事件處理函數(shù)更新狀態(tài);Vue 的 v-model 是雙向數(shù)據(jù)綁定,修改表單元素的值會(huì)自動(dòng)更新數(shù)據(jù),反之亦然。
非受控組件
React 非受控組件
在 React 中,非受控組件通過 ref 來訪問 DOM 元素,從而獲取表單元素的值。
import React, { useRef } from 'react'; function ReactUncontrolledInput() { // 創(chuàng)建一個(gè) ref 對象 const inputRef = useRef(null); // 處理表單提交的函數(shù) const handleSubmit = (e) => { e.preventDefault(); // 通過 ref 獲取輸入框的值 const value = inputRef.current.value; console.log('輸入內(nèi)容:', value); }; return ( <form onSubmit={handleSubmit}> {/* 將 ref 綁定到輸入框 */} <input type="text" ref={inputRef} /> <button type="submit">提交</button> </form> ); } export default ReactUncontrolledInput;
Vue 非受控組件
在 Vue 里,非受控組件可通過 ref 來訪問 DOM 元素。不過,Vue 更強(qiáng)調(diào)數(shù)據(jù)驅(qū)動(dòng),使用非受控組件的場景相對較少。
<template> <form @submit.prevent="handleSubmit"> <!-- 給輸入框添加 ref --> <input type="text" ref="inputRef" /> <button type="submit">提交</button> </form> </template> ???????<script> export default { methods: { handleSubmit() { // 通過 $refs 獲取輸入框的值 const value = this.$refs.inputRef.value; console.log('輸入內(nèi)容:', value); } } }; </script>
區(qū)別總結(jié)
- 語法方面:React 使用 useRef 鉤子創(chuàng)建 ref 對象,而 Vue 直接在模板中使用 ref 屬性,在腳本里通過 this.$refs 來訪問。
- 使用頻率:React 里非受控組件的使用較為常見,而 Vue 更傾向于使用數(shù)據(jù)驅(qū)動(dòng)的方式,非受控組件的使用場景相對較少。
綜上所述,React 和 Vue 在受控組件和非受控組件的實(shí)現(xiàn)上各有特點(diǎn),你可以根據(jù)項(xiàng)目需求和個(gè)人習(xí)慣來選擇合適的方式。
到此這篇關(guān)于React中如何實(shí)現(xiàn)受控組件與非受控組件的文章就介紹到這了,更多相關(guān)React受控組件與非受控組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react hooks實(shí)現(xiàn)防抖節(jié)流的方法小結(jié)
這篇文章主要介紹了react hooks實(shí)現(xiàn)防抖節(jié)流的幾種方法,文中通過代碼示例給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-04-04詳解對于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能
這篇文章主要介紹了詳解對于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04React工作流程及Error Boundaries實(shí)現(xiàn)過程講解
這篇文章主要介紹了React工作流程及Error Boundaries實(shí)現(xiàn)過程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-02-02React ant 點(diǎn)擊導(dǎo)航條閃爍問題解決
很多小伙伴反饋React ant 點(diǎn)擊導(dǎo)航條閃爍,沒有傳遞具體的參數(shù)給點(diǎn)擊事件 , 導(dǎo)致在函數(shù)內(nèi)部無法準(zhǔn)確判斷要展示哪個(gè)子菜單,可能導(dǎo)致頁面狀態(tài)的短暫變化,出現(xiàn)閃爍效果,下面給大家分享解決方法,感興趣的的朋友跟隨小編一起看看吧2024-04-04