React使用hook如何實(shí)現(xiàn)數(shù)據(jù)雙向綁定
React使用hook實(shí)現(xiàn)數(shù)據(jù)雙向綁定
寫(xiě)在前面:閱讀hook的使用前,要對(duì)Class實(shí)現(xiàn)方法有一定了解,我們也從這里開(kāi)始講起:
const root = ReactDOM.createRoot(document.getElementById('root')); function tick() { const element = ( <div> <h1>Hello, world!</h1> <h2>It is {new Date().toLocaleTimeString()}.</h2> </div> ); root.render(element);} setInterval(tick, 1000);
在react初級(jí),我們學(xué)會(huì)了使用ReactDOM進(jìn)行元素的掛載、使用jsx模式編輯可視化更強(qiáng)的(<html />)、通過(guò)setInterval實(shí)現(xiàn)function的調(diào)用;如何使用Class進(jìn)行更加規(guī)范性和可編輯性的代碼書(shū)寫(xiě)呢?
在React官方文檔有如下的步驟:
- 創(chuàng)建一個(gè)同名的 ES6 class,并且繼承于
React.Component
。 - 添加一個(gè)空的
render()
方法。 - 將函數(shù)體移動(dòng)到
render()
方法之中。 - 在
render()
方法中使用this.props
替換props
。 - 刪除剩余的空函數(shù)聲明。
首先,應(yīng)用Class在我看來(lái)是一個(gè)必不可少的策略,因?yàn)樵嫉膉s編輯模式和引入react,使用react DOM進(jìn)行掛載的方式過(guò)分原始,并且缺少作用域的劃分,缺少可復(fù)用性,甚至在你想要多實(shí)現(xiàn)一個(gè)功能時(shí)變得很被動(dòng)。
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.date.toLocaleTimeString()}.</h2> </div> ); } } function tick() { ReactDOM.render( <Clock date={new Date()} />, document.getElementById('root') ); } setInterval(tick, 1000);
哪怕我們沒(méi)有對(duì)Java足夠熟悉,也并不清楚js中類(lèi)和繼承的底層原理,但是直觀地,class的出現(xiàn),讓我們很快的想到一個(gè)詞,那就是“面向?qū)ο?rdquo;。
眾所周知的時(shí),JS并非面向?qū)ο蟮牡兆?,而是在發(fā)展后期不斷通過(guò)新的貢獻(xiàn)而看上去(或者說(shuō)使用上)更加的面向?qū)ο螅鳛殚_(kāi)發(fā)程序的工程師,尤其是遇“JS”不久的小白而言,使用是優(yōu)于理解的,因?yàn)橹挥袑?shí)踐,才是掌握理論的不二法門(mén)。
接下來(lái),我們通過(guò)一段相同效果的代碼來(lái)說(shuō)Class的問(wèn)題和hook的使用:
import React, { useState } from 'react'; function Example() { // 聲明一個(gè)叫 "count" 的 state 變量 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
誠(chéng)然,代碼行數(shù)的減少可以使我們顯得更加專(zhuān)業(yè)和高級(jí),function的聲明也似乎比class extends React.Component 云云更精簡(jiǎn),不過(guò)真正值得注意的不僅僅于此:
關(guān)于this:
有過(guò)前端面試經(jīng)驗(yàn)的小伙伴都清楚,this使用不當(dāng)是一件很不好的事情,如果你想學(xué)好this,可以到掘金刷刷前端經(jīng)典面試題,或者沒(méi)事的時(shí)候打開(kāi)Chrome的F12來(lái)動(dòng)手試試,不過(guò)在你尚未吃透這個(gè)原理的所有場(chǎng)景,或者你單純就是個(gè)謹(jǐn)慎的程序開(kāi)發(fā)者,那么避免在一些可能出錯(cuò)的地方使用this將會(huì)是一個(gè)很好的選擇,Hook的操作最大優(yōu)點(diǎn)由此顯示:通過(guò)前端開(kāi)發(fā)的同學(xué)們更加熟悉的function寫(xiě)法,避免在各層調(diào)用中this指向不準(zhǔn)而導(dǎo)致bug的出現(xiàn);除此之外,通過(guò)count, setCount的綁定方法分離state和action層,const阻止變量污染,以上,是我想要分享的hook的優(yōu)勢(shì),接下來(lái)將介紹hook的使用方法:useState, useEffect。
(新內(nèi)容)
關(guān)于useState
基于上述內(nèi)容,我們已經(jīng)清楚hook的聲明方式:
const [count, setCount] = useState(0); // 0是初始值
我們從這條語(yǔ)句開(kāi)始說(shuō)起,const是ES6中對(duì)于不可改變的量的聲明方式,我們可以清晰地得到“不可以在程序中直接修改count的值"的字面意思,[ ]只是形式不去管他,count和setCount由自己定義,我們習(xí)慣于將前面的變量加上set的名稱(chēng)作為其修改方法,useState固定寫(xiě)法,( 0 )是初始值,可以傳入js中有實(shí)際意義的各類(lèi)對(duì)象,例如對(duì)象{}數(shù)組[]時(shí)間new Date或者一個(gè)簡(jiǎn)單的null。
關(guān)于set方法
第一次接觸的同學(xué)會(huì)有疑問(wèn)?如何使用修改方法呢,很簡(jiǎn)單,在相同的上下文內(nèi),直接使用setCount(*新的值*),“那上下文...." 還是轉(zhuǎn)化成白話文吧:在當(dāng)下組件可以直接使用,把useState聲明的值當(dāng)作當(dāng)前組件的私有變量,如果需要在其他地方使用,請(qǐng)學(xué)習(xí)如何傳值(這是另外一個(gè)話題,也可能在接下來(lái)一段時(shí)間更新到后續(xù)文章);
學(xué)習(xí)到此,我們大概會(huì)覺(jué)得這個(gè)方法好極了,不會(huì)被污染,自己私域可用,寫(xiě)法規(guī)范,可以綁定到DOM上,等等,記得開(kāi)始時(shí)候我們說(shuō)得是雙向綁定,set方法對(duì)應(yīng)的應(yīng)該有一個(gè)get才對(duì),那么hook的使用方法是什么呢?
異步與副作用:
首先來(lái)看一段不簡(jiǎn)單的代碼:
const [count, setCount] = useState(0); setCount(1); console.log(count); // 控制臺(tái)輸出:0
好學(xué)的你一定知道這是setCount方法的異步性,官方文檔給的解釋叫做:“useState可能是個(gè)異步操作”,如何理解可能不重要,我們不可能將程序置于可能當(dāng)中,于是官方提供了useState的兄弟方法:useEffect。
關(guān)于useEffect
const [count, setCount] = useState(0); setCount(1); console.log(count); // 控制臺(tái)輸出:0 useEffect(() => { console.log(count); // 控制臺(tái)輸出:1 });
這段代碼不做解釋?zhuān)又鴣?lái)講:
熟悉vue的同學(xué)在開(kāi)發(fā)過(guò)程中應(yīng)當(dāng)會(huì)應(yīng)用到computed和watch屬性,使得頁(yè)面的數(shù)據(jù)保持“時(shí)時(shí)正確”性,很多情況,一個(gè)按鈕會(huì)導(dǎo)致多個(gè)展示項(xiàng)的刷新,而延誤是我們應(yīng)當(dāng)避免的,useEffect就是這樣一個(gè)方法,他會(huì)在react內(nèi)部啟動(dòng)監(jiān)聽(tīng),當(dāng)某個(gè)對(duì)象發(fā)生改變,觸發(fā)響應(yīng)的函數(shù),在這個(gè)函數(shù)中我們可以使用上述的useState所聲明的set方法改變某個(gè)綁定到頁(yè)面的數(shù)據(jù)項(xiàng)從而渲染新的頁(yè)面。
舉手:你剛剛講的“某個(gè)對(duì)象”是怎么一回事?
請(qǐng)看這段代碼:
useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // 僅在 count 更改時(shí)更新
OK,當(dāng)你閱讀到這個(gè)位置,就已經(jīng)有相當(dāng)深入的“入門(mén)“知識(shí)了,你可以選擇新建一個(gè)react項(xiàng)目,隨便輸出幾條內(nèi)容,綁定一兩個(gè)數(shù)據(jù),實(shí)踐出真知。
接著看代碼,我們通常——或者說(shuō)被規(guī)定——使用useEffect(function(), props);的方式來(lái)綁定useEffect的監(jiān)視對(duì)象,在上面的例子中,count的值發(fā)生改變(by any reason)就會(huì)隨之進(jìn)行標(biāo)題修改的語(yǔ)句。
OK,那么props既然是數(shù)組,我們可以傳入多條監(jiān)視源么?No。
使用Effect方法可以解決useState的異步問(wèn)題么?Yes。
使用Effect方法能實(shí)現(xiàn)聲明周期函數(shù)么?是的,我們將props的內(nèi)容填空,即[],就會(huì)在組件創(chuàng)建之初進(jìn)行一次且僅一次的調(diào)用,類(lèi)似于Vue中的created聲明周期鉤子。
useEffect方法有異步性么?無(wú)關(guān)緊要,因?yàn)轫?yè)面會(huì)隨著useEffect中的語(yǔ)句更新。
useEffect的實(shí)現(xiàn)方式是什么樣的?useEffect因?yàn)榭梢员O(jiān)測(cè)多個(gè)數(shù)據(jù)源,故一個(gè)組件會(huì)存在多個(gè)use Effect函數(shù),他們會(huì)被當(dāng)做一個(gè)整體,也就是一顆方法樹(shù),每個(gè)新的方法都會(huì)掛載在上面,在發(fā)生改變之后,整顆樹(shù)一塊刷新,并對(duì)應(yīng)DOM樹(shù)進(jìn)行改變。
關(guān)于Hook額外的信息
不要在循環(huán),條件或嵌套函數(shù)中調(diào)用 Hook, 確??偸窃谀愕?React 函數(shù)的最頂層以及任何 return 之前調(diào)用他們。
遵守這條規(guī)則,你就能確保 Hook 在每一次渲染中都按照同樣的順序被調(diào)用。
這讓 React 能夠在多次的 useState
和 useEffect
調(diào)用之間保持 hook 狀態(tài)的正確。(如果你對(duì)此感到好奇,我們?cè)谙旅鏁?huì)有更深入的解釋。)
不要在非react代碼中使用Hook。
總結(jié)
(以上內(nèi)容類(lèi)似與考試須知,請(qǐng)大家自行理解)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Remix集成antd和pro-components的過(guò)程示例
這篇文章主要為大家介紹了Remix集成antd和pro-components的過(guò)程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03React中使用react-json-view展示JSON數(shù)據(jù)的操作方法
react-json-view是一個(gè)用于顯示和編輯javascript數(shù)組和JSON對(duì)象的React組件,本文給大家分享React中使用react-json-view展示JSON數(shù)據(jù)的操作方法,感興趣的朋友一起看看吧2023-12-12如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過(guò)濾器
這篇文章主要介紹了如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過(guò)濾器,在vue及react中經(jīng)常會(huì)遇到,今天通過(guò)實(shí)例代碼給大家講解,需要的朋友可以參考下2018-11-11antd-react使用Select組件defaultValue踩的坑及解決
這篇文章主要介紹了antd-react使用Select組件defaultValue踩的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05詳解React中的useMemo和useCallback的區(qū)別
React中的useMemo和useCallback是兩個(gè)重要的Hooks。常常被用于優(yōu)化組件的性能。雖然這兩個(gè)Hooks看起來(lái)很相似,但它們彼此之間還是有很大的區(qū)別的,隨著小編一起來(lái)學(xué)習(xí)吧2023-04-04