React數(shù)據(jù)傳遞之組件內(nèi)部通信的方法
1. 概述
脫離初級(jí)前端一段時(shí)間后會(huì)發(fā)現(xiàn),寫(xiě)樣式的時(shí)間越來(lái)越少,處理數(shù)據(jù)的時(shí)間越來(lái)越多。處理數(shù)據(jù)的過(guò)程也就是實(shí)現(xiàn)業(yè)務(wù)邏輯的過(guò)程,這在項(xiàng)目中無(wú)疑是最重要的。
所以學(xué)習(xí)前端框架,了解完基本語(yǔ)法后,接下來(lái)就要學(xué)習(xí)其如何進(jìn)行數(shù)據(jù)傳遞。
Angular 設(shè)計(jì)之初的一大亮點(diǎn)就是實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定,使用 Vue 一段時(shí)間后發(fā)現(xiàn),所謂數(shù)據(jù)的雙向綁定,組件內(nèi)部唯一的應(yīng)用場(chǎng)景就是 form 表單(input,textarea,select, radio),而這種場(chǎng)景下的數(shù)據(jù)雙向綁定,即便框架內(nèi)部沒(méi)有實(shí)現(xiàn),自己實(shí)現(xiàn)起來(lái)也非常簡(jiǎn)單。明白這一點(diǎn)后感覺(jué)之前認(rèn)為 React 沒(méi)有實(shí)現(xiàn)數(shù)據(jù)雙向綁定很 low 的想法很幼稚。
對(duì)于 React 的數(shù)據(jù)傳遞,涉及兩方面的內(nèi)容:
- 組件內(nèi)部的數(shù)據(jù)傳遞,典型的應(yīng)用場(chǎng)景包括如何實(shí)現(xiàn) form 表單雙向數(shù)據(jù)綁定、如何綁定事件;
- 組件間的數(shù)據(jù)傳遞。 包括父組件往子組件傳遞數(shù)據(jù)、子組件往父組件傳遞數(shù)據(jù)以及兄弟組件之間傳遞數(shù)據(jù)。
本文先討論組件內(nèi)部的數(shù)據(jù)傳遞。
2. 組件內(nèi)部數(shù)據(jù)傳遞
React 組件內(nèi)部通信主要分為兩部分:數(shù)據(jù)展示與事件處理。
2.1 數(shù)據(jù)展示
組件內(nèi)部數(shù)據(jù)的展示和更新都是通過(guò) state 來(lái)實(shí)現(xiàn)的,如果要使用 state 必須使用 ES6 的 class 定義組件。數(shù)據(jù)更新在雙向數(shù)據(jù)綁定部分探討,這部分僅討論展示初始化數(shù)據(jù)。
如果你熟悉 Vue,React 的 state 對(duì)象相當(dāng)于 Vue 的 data 對(duì)象
下面是一個(gè)純展示數(shù)據(jù)的示例:
class App extends Component { constructor(props) { super(props); // 初始化 state this.state = { inputValue: "test", }; } render() { // 注意,在 react 中,DOM 元素是對(duì)象,所以使用‘()'包住 return ( <div className="App"> <p>{this.state.inputValue}</p> </div> ); } }
在通過(guò) class 定義的 React 組件中,除了生命周期鉤子函數(shù), constructor() 和 render() 著兩個(gè)方法也是自動(dòng)執(zhí)行的,先執(zhí)行 constructor() ,執(zhí)行 constructor() 的同時(shí)也是再為 render() 渲染 DOM 做數(shù)據(jù)準(zhǔn)備。
實(shí)際上 constructor() 函數(shù)是組件生命周期中調(diào)用的第一個(gè)函數(shù)。
2.2 事件
2.2.1 與 DOM 中事件的異同
在 React 中處理事件和在 DOM 中處理事件類(lèi)似,有兩點(diǎn)不同:
- React 中通過(guò)駝峰命名法命名事件,而不是全是小寫(xiě)字母;
- 在 JSX 中直接傳遞函數(shù)作為事件處理程序,而不是字符串。
第 2 點(diǎn)不同有坑,后面細(xì)說(shuō)
舉個(gè)例子,HTML中的事件:
<button onclick="activateLasers()"> Activate Lasers </button>
React 中的事件:
// 因?yàn)?jsx 中'{}'里面代表函數(shù)表達(dá)式, // 所以傳遞給 onClick 的實(shí)際是函數(shù) activateLasers 的函數(shù)體部分, // 因此需要指定 this 指向,不然會(huì)報(bào)錯(cuò) <button onClick={activateLasers}> Activate Lasers </button>
2.2.2 存在的坑
直接傳遞 function 作為 event handler 需要指定函數(shù)的執(zhí)行環(huán)境,即需要手動(dòng)綁定 this ,不然會(huì)報(bào) this 為 undefined 的錯(cuò)。見(jiàn)下面的例子:
class App extends Component { constructor(props) { super(props); this.state = { isToggleOn: true, }; // 手動(dòng)綁定 this this.handleClick = this.handleClick.bind(this); } handleClick() { // 如果不在 constructor() 方法中手動(dòng)綁定 this,直接將其作為事件處理程序 this 為 undefined console.log(this); this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <div className="App"> <button onClick={this.handleClick}> {this.state.isToggleOn ? "on" : "off"} </button> </div> ); } }
2.2.3 為什么會(huì)有坑
React 官網(wǎng) 說(shuō)這個(gè)鍋要 JS 原生語(yǔ)法來(lái)背,其實(shí)不盡然,React 實(shí)在 JS 語(yǔ)法早已確定的情況下設(shè)計(jì)了這樣的事件系統(tǒng),如果一定要有人站出來(lái)背鍋,他們五五分吧。
1, JS原生語(yǔ)法存在的問(wèn)題
JS語(yǔ)法中有這樣的規(guī)則:如果將一個(gè)函數(shù)的函數(shù)體(沒(méi)有 () )賦值給另一個(gè)變量,函數(shù)體內(nèi)部的 this 指向可能會(huì)發(fā)生變化。會(huì)不會(huì)變化取決于函數(shù)和被賦值的變量是否處于同一個(gè)作用域(相同的執(zhí)行環(huán)境)中,但實(shí)際使用中,將一個(gè)函數(shù)賦值給相同作用域的變量沒(méi)有意義,那樣的話直接使用那個(gè)函數(shù)就好,沒(méi)必要在賦值給另一個(gè)變量。
this 指向不發(fā)生改變的沒(méi)有意義的例子(為了方便說(shuō)明,直接使用 var 操作符):
var fn = function () { console.log(this); }; var a = fn; fn(); // window a(); // window this 指向發(fā)生改變的例子: var fn = function () { console.log(this); }; // 將函數(shù)體賦值給一個(gè)對(duì)象的屬性,函數(shù)執(zhí)行時(shí) this 和定義時(shí)指向不同 var o = { a: fn, }; fn(); // window o.a(); // o,即{a:f}
如果想要在將函數(shù)體賦值另一個(gè)變量的同時(shí)把原函數(shù)的 this 指向也一塊賦值過(guò)去,就需要在賦值的過(guò)程中進(jìn)行綁定 this 的操作,如下:
var fn = function () { console.log(this); }; // fn 在賦值的同時(shí)將內(nèi)部的 this 打包一塊賦值給了 a var o = { a: fn.bind(this), }; fn(); // window o.a(); // window
通常在將函數(shù)體賦值給變量的時(shí)候?yàn)榱吮苊?this 出錯(cuò),都會(huì)進(jìn)行 綁定執(zhí)行環(huán)境的操作 ,典型的例子是 var bindId = document.getElementById.bind(document)
2, JSX 存在的問(wèn)題
因?yàn)?JSX 中 DOM 元素也是對(duì)象,給元素的屬性賦值實(shí)際是給 DOM 元素對(duì)象的屬性賦值,見(jiàn)下:
const element = ( <button onClick={this.handleClick}>click me</button> );
等同于
const element = { type: 'button', props: { onClick: this.handleClick, children: 'click me', }, };
這實(shí)際就是 將函數(shù)體賦值給一個(gè)對(duì)象的屬性,函數(shù)執(zhí)行時(shí) this 和定義時(shí)指向不同 的場(chǎng)景,和原生語(yǔ)法相同的是 this 指向發(fā)生了改變,不同的是原生 JS 中不管怎樣, this 總歸是有個(gè)指向的,而 JSX 直接 undefined 。
所以說(shuō)不綁定 this 報(bào) undefined 的錯(cuò)不能全怪 JS 原生語(yǔ)法。
3. 雙向數(shù)據(jù)綁定
通過(guò) state 傳遞數(shù)據(jù)加上事件處理程序便能實(shí)現(xiàn)數(shù)據(jù)的雙向綁定,其背后的思想是(以 input 為例):初始化時(shí)將 state 中預(yù)定義的 state a 賦值給 input,當(dāng) input 的 value 發(fā)生改變時(shí),觸發(fā)事件處理程序,將改變后的 value 賦值給狀態(tài) a ,React 監(jiān)測(cè)到 state 改變時(shí)重新調(diào)用 render() 方法,即重新渲染組件,達(dá)到雙向綁定的目的。
class App extends Component { constructor(props) { super(props); this.state = { inputValue: "test", }; this.changeInput = this.changeInput.bind(this); } changeInput(e) { // 將改變后的 input 值賦值給 inputValue,通過(guò)事件對(duì)象 $event.target.value 實(shí)現(xiàn) this.setState({ inputValue: e.target.value }); } render() { // input 改變時(shí)觸發(fā) changeInput return ( <div className="App"> <input value={this.state.inputValue} onChange={this.changeInput} /> <p>{this.state.inputValue}</p> </div> ); } }
這里用到了事件對(duì)象,React 的事件對(duì)象和 JS 原生事件對(duì)象保持一致。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
React狀態(tài)更新的優(yōu)先級(jí)機(jī)制源碼解析
這篇文章主要為大家介紹了React狀態(tài)更新的優(yōu)先級(jí)機(jī)制源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11react 報(bào)錯(cuò)Module build failed: Browserslis
這篇文章主要介紹了react 報(bào)錯(cuò)Module build failed: BrowserslistError: Unknown browser query `dead`問(wèn)題的解決方法,需要的朋友可以參考下2023-06-06可定制react18 input otp 一次性密碼輸入組件
這篇文章主要為大家介紹了可定制react18 input otp 一次性密碼輸入組件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10React-Native之定時(shí)器Timer的實(shí)現(xiàn)代碼
本篇文章主要介紹了React-Native之定時(shí)器Timer的實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10react中實(shí)現(xiàn)拖拽排序react-dnd功能
這篇文章主要介紹了react中實(shí)現(xiàn)拖拽排序react-dnd功能,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02React中使用axios發(fā)送請(qǐng)求的幾種常用方法
本文主要介紹了React中使用axios發(fā)送請(qǐng)求的幾種常用方法,主要介紹了get和post請(qǐng)求,具有一定的參考價(jià)值,感興趣的可以了解一下2021-08-08