您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“React如何從Class方式轉(zhuǎn)Hooks”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“React如何從Class方式轉(zhuǎn)Hooks”這篇文章吧。
Hooks很大的一個亮點是可以進(jìn)行業(yè)務(wù)邏輯的重用。這一點在hooks中體現(xiàn)的尤為明顯。比如,往常的class中如果要去監(jiān)聽窗口大小的變化的時候,就得在組件中在掛載后去添加監(jiān)聽事件,但是如果當(dāng)另外一個地方需要用到這種監(jiān)聽窗口大小功能的話,這種邏輯代碼并不可以復(fù)用,只能在那個組件中重新寫一遍。但是在hooks中,我們可以將這部分監(jiān)聽的邏輯代碼進(jìn)行hooks方式封裝,完全可以做到邏輯上的復(fù)用。
使用Class作為React的載體的時候:
組件之間不會相互繼承,沒有利用到class的繼承的特性UI是狀態(tài)驅(qū)動的,所有的方法都是內(nèi)部調(diào)用或者作為生命周期的方法內(nèi)部自動調(diào)用。沒有使用到類的實例方法可以調(diào)用的特性
React中的一個核心就是要實現(xiàn)從State數(shù)據(jù)到View試圖層面的一個綁定。使用函數(shù),其實更好的去解決State到View的一個映射問題。但是,用函數(shù)作為React的載體就會出現(xiàn)兩個問題,函數(shù)中狀態(tài)的保存以及生命周期的方法。
Hooks怎樣去解決上面兩個問題:把一個外部的數(shù)據(jù)綁定到函數(shù)的執(zhí)行。當(dāng)數(shù)據(jù)變化時,讓函數(shù)能夠自動重新執(zhí)行。這樣的話,任何會影響 UI 展現(xiàn)的外部數(shù)據(jù),都可以通過這個機制綁定到 React 的函數(shù)組件。
Hooks鉤子的理解:把某個目標(biāo)結(jié)果鉤到某個可能會變化的數(shù)據(jù)源或者事件源上,那么當(dāng)被鉤到的數(shù)據(jù)或事件發(fā)生變化時,產(chǎn)生這個目標(biāo)結(jié)果的代碼會重新執(zhí)行,產(chǎn)生更新后的結(jié)果
圖解:一個執(zhí)行過程(Execution),例如是函數(shù)組件本身,可以綁定在(鉤在)傳統(tǒng)意義的 State,或者 URL,甚至可以是窗口的大小。這樣當(dāng) State、URL、窗口大小發(fā)生變化時,都會重新執(zhí)行某個函數(shù),產(chǎn)生更新后的結(jié)果。
比起 Class 組件,函數(shù)組件是更適合去表達(dá) React 組件的執(zhí)行的,因為它更符合 State => View 這樣的一個邏輯關(guān)系。但是因為缺少狀態(tài)、生命周期等機制,讓它一直功能受限。Hooks解決了函數(shù)組件作為React載體的狀態(tài)生命周期等受限問題,讓其功能充分發(fā)揮出來
Hooks 中被鉤的對象,可以是某個獨立的數(shù)據(jù)源,也可以是另一個 Hook 執(zhí)行的結(jié)果,這就帶來了 Hooks 的最大好處:邏輯的復(fù)用
簡化了邏輯復(fù)用
Class方式中:使用高階組件的設(shè)計模式進(jìn)行邏輯復(fù)用。比如:我們要去復(fù)用一個窗口resize的功能,我們需要去定義一個沒有UI的外層組件,去寫相關(guān)resize的邏輯定義,然后將數(shù)據(jù)結(jié)果用屬性的方式傳給子組件。組件要復(fù)用這個邏輯的話,必須外層用這個組件包裹并返回。針對整個而言,**為了傳遞一個外部的狀態(tài),我們不得不定義一個沒有 UI 的外層組件,而這個組件只是為了封裝一段可重用的邏輯。**頻繁使用,每一個高階組件的使用都會多一層節(jié)點,會給調(diào)試等帶來很大的負(fù)擔(dān)。
//Class中高階組件實現(xiàn)resize方法復(fù)用 //1、高階組件的聲明 const withWindowSize = Component => { // 產(chǎn)生一個高階組件 WrappedComponent,只包含監(jiān)聽窗口大小的邏輯 class WrappedComponent extends React.PureComponent { constructor(props) { super(props); this.state = { size: this.getSize() }; } componentDidMount() { window.addEventListener("resize", this.handleResize); } componentWillUnmount() { window.removeEventListener("resize", this.handleResize); } getSize() { return window.innerWidth > 1000 ? "large" :"small"; } handleResize = ()=> { const currentSize = this.getSize(); this.setState({ size: this.getSize() }); } render() { // 將窗口大小傳遞給真正的業(yè)務(wù)邏輯組件 return <Component size={this.state.size} />; } } return WrappedComponent; }; //2、組件MyComponent使用高階組件中的resize功能 class MyComponent extends React.Component{ render() { const { size } = this.props; if (size === "small") return <SmallComponent />; else return <LargeComponent />; } } // 使用 withWindowSize 產(chǎn)生高階組件,用于產(chǎn)生 size 屬性傳遞給真正的業(yè)務(wù)組件 export default withWindowSize(MyComponent);
Hooks方式中:實現(xiàn)resize的話,窗口大小只是外部的一個數(shù)據(jù)狀態(tài)。我們使用hooks方式對其封裝,只是將其變成了一個可以綁定的數(shù)據(jù)源,當(dāng)窗口大小發(fā)生變化的時候,這個組件也會重新渲染代碼會更加簡潔直觀,并且不會產(chǎn)生額外的組件節(jié)點。
//Hooks中使用hooks方法進(jìn)行resize邏輯復(fù)用 //定義useWindowSize這個hook const getSize = () => { return window.innerWidth > 1000 ? "large" : "small"; } const useWindowSize = () => { const [size, setSize] = useState(getSize()); useEffect(() => { const handler = () => { setSize(getSize()) }; window.addEventListener('resize', handler); return () => { window.removeEventListener('resize', handler); }; }, []); return size; }; //函數(shù)組件中使用這個hook const Demo = () => { const size = useWindowSize(); if (size === "small") return <SmallComponent />; else return <LargeComponent />; };
有助于關(guān)注分離
Hooks能夠讓針對同一個業(yè)務(wù)邏輯的代碼盡可能聚合在一塊,在Class組件中不得不吧同一個業(yè)務(wù)邏輯代碼分散在類組件的不同的生命周期方法中
圖解:左側(cè)是 Class 組件,右側(cè)是函數(shù)組件結(jié)合 Hooks。藍(lán)色和黃色代表不同的業(yè)務(wù)功能
React一共提供了10個Hooks
,useState
、useEffect
、useCallback
、useMemo
、useRef
、useContext
等等
我們要遵循的一個原則就是:state 中永遠(yuǎn)不要保存可以通過計算得到的值,例如:
從 props 傳遞過來的值。有時候 props 傳遞過來的值無法直接使用,而是要通過一定的計算后再在 UI 上展示,比如說排序。那么我們要做的就是每次用的時候,都重新排序一下,或者利用某些 cache 機制,而不是將結(jié)果直接放到 state 里。
從 URL 中讀到的值。比如有時需要讀取 URL 中的參數(shù),把它作為組件的一部分狀態(tài)。那么我們可以在每次需要用的時候從 URL 中讀取,而不是讀出來直接放到 state 里。
從 cookie、localStorage 中讀取的值。通常來說,也是每次要用的時候直接去讀取,而不是讀出來后放到 state 里。
副作用是指一段和當(dāng)前執(zhí)行結(jié)果無關(guān)的代碼。比如說要修改函數(shù)外部的某個變量,要發(fā)起一個請求。形式:useEffect(callback, dependencies)
。涵蓋了componentDidMount
、componentDidUpdate
和componentWillUnmount
三個生命周期方法。簡而言之,useEffect 是每次組件 render 完后判斷依賴并執(zhí)行。
使用useEffect應(yīng)該注意的點:
沒有依賴項,則每次 render 后都會重新執(zhí)行
useEffect(()=>{ console.log('re-render') //每次render完成一次后就執(zhí)行 })
空數(shù)組作為依賴項,則只在首次執(zhí)行時觸發(fā),對應(yīng)到 Class 組件就是 componentDidMount
useEffect(()=>{ console.log('did mount') //相當(dāng)于componentDidMount },[])
可以返回一個函數(shù),用在組件銷毀的時候做一些清理的操作
const [size,setResize] = useState({}) useEffect(()=>{ const handler = () => { setResize() } window.addEventListener('resize',handler) return ()=>{ window.removeEventListener('resize',handler) } },[])
以上是“React如何從Class方式轉(zhuǎn)Hooks”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。