久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

react hook和class的區(qū)別有哪些

區(qū)別:1、hooks的寫法比class簡潔;2、hooks的業(yè)務(wù)代碼比class更加聚合;3、class組件的邏輯復(fù)用通常用render props以及HOC兩種方式,而react hooks提供了自定義hooks來復(fù)用邏輯。

react hook和class的區(qū)別有哪些

本教程操作環(huán)境:Windows7系統(tǒng)、react17.0.1版、Dell G3電腦。

react hooks與class組件有哪些區(qū)別?下面就來帶大家對比一下react hooks和class組件,聊聊它們的區(qū)別。

react-hooks解決的問題

  • 函數(shù)組件中不能擁有自己的狀態(tài)(state)。在hooks之前函數(shù)組件是無狀態(tài)的,都是通過props來獲取父組件的狀態(tài),但是hooks提供了useState來維護(hù)函數(shù)組件內(nèi)部的狀態(tài)。

  • 函數(shù)組件中不能監(jiān)聽組件的生命周期。useEffect聚合了多個(gè)生命周期函數(shù)。

  • class組件中生命周期較為復(fù)雜(在15版本到16版本的變化大)。

  • class組件邏輯難以復(fù)用(HOC,render props)。

hooks對比class的好處(對比)

1、寫法更加的簡潔

我們以最簡單的計(jì)數(shù)器為例:

class組件

class ExampleOfClass extends Component {   constructor(props) {     super(props)     this.state = {       count: 1     }   }   handleClick = () => {     let { count } = this.state     this.setState({       count: count+1     })   }   render() {     const { count } = this.state     return (       <div>         <p>you click { count }</p>         <button onClick={this.handleClick}>點(diǎn)擊</button>       </div>     )   } }

hooks

function ExampleOfHooks() {     const [count, setCount] = useState(0)     const handleClick = () => {         setCount(count + 1)     }     return (       <div>         <p>you click { count }</p>         <button onClick={handleClick}>點(diǎn)擊</button>       </div>     ) }

可以看到使用hooks的代碼相比class組件代碼更加的簡潔、清晰。

2、業(yè)務(wù)代碼更加聚合

使用class組件經(jīng)常會出現(xiàn)一個(gè)功能出現(xiàn)在兩個(gè)生命周期函數(shù)內(nèi)的情況,這樣分開寫有時(shí)候可能會忘記。比如:

let timer = null componentDidMount() {     timer = setInterval(() => {         // ...     }, 1000) } // ... componentWillUnmount() {     if (timer) clearInterval(timer) }

由于添加定時(shí)器和清除定時(shí)器是在兩個(gè)不同的生命周期函數(shù),中間可能會有很多其他的業(yè)務(wù)代碼,所以可能會忘記清除定時(shí)器,如果在組件卸載時(shí)沒有添加清楚定時(shí)器的函數(shù)就可能會造成內(nèi)存泄漏、網(wǎng)絡(luò)一直請求等問題。

但是使用hooks可以讓代碼更加的集中,方便我們管理,也不容易忘記:

useEffect(() => {     let timer = setInterval(() => {         // ...     }, 1000)     return () => {         if (timer) clearInterval(timer)     } }, [//...])

3、邏輯復(fù)用方便

class組件的邏輯復(fù)用通常用render props以及HOC兩種方式。react hooks提供了自定義hooks來復(fù)用邏輯。

下面以獲取鼠標(biāo)在頁面的位置的邏輯復(fù)用為例:

class組件render props方式復(fù)用

import React, { Component } from 'react'  class MousePosition extends Component {   constructor(props) {     super(props)     this.state = {       x: 0,       y: 0     }   }    handleMouseMove = (e) => {     const { clientX, clientY } = e     this.setState({       x: clientX,       y: clientY     })   }    componentDidMount() {     document.addEventListener('mousemove', this.handleMouseMove)   }    componentWillUnmount() {     document.removeEventListener('mousemove', this.handleMouseMove)   }    render() {     const { children } = this.props     const { x, y } = this.state     return(       <div>         {           children({x, y})         }       </div>     )   }  }  // 使用 class Index extends Component {   constructor(props) {     super(props)   }    render() {     return (       <MousePosition>         {           ({x, y}) => {             return (               <div>                 <p>x:{x}, y: {y}</p>               </div>             )           }         }       </MousePosition>     )   } }  export default Index

自定義hooks方式復(fù)用

import React, { useEffect, useState } from 'react'  function usePosition() {   const [x, setX] = useState(0)   const [y, setY] = useState(0)    const handleMouseMove = (e) => {     const { clientX, clientY } = e     setX(clientX)     setY(clientY)   }     useEffect(() => {     document.addEventListener('mousemove', handleMouseMove)     return () => {       document.removeEventListener('mousemove', handleMouseMove)     }   })   return [     {x, y}   ] }  // 使用 function Index() {   const [position] = usePosition()   return(     <div>       <p>x:{position.x},y:{position.y}</p>     </div>   ) }  export default Index

可以很明顯的看出使用hooks對邏輯復(fù)用更加的方便,使用的時(shí)候邏輯也更加清晰。

hooks常見的一些API使用

1、useState

語法

const [value, setValue] = useState(0)

這種語法方式是ES6的數(shù)組結(jié)構(gòu),數(shù)組的第一個(gè)值是聲明的狀態(tài),第二個(gè)值是狀態(tài)的改變函數(shù)。

每一幀都有獨(dú)立的狀態(tài)

個(gè)人理解針對每一幀獨(dú)立的狀態(tài)是采用了閉包的方法來實(shí)現(xiàn)的。

function Example() {   const [val, setVal] = useState(0)   const timeoutFn = () => {       setTimeout(() => {         // 取得的值是點(diǎn)擊按鈕的狀態(tài),不是最新的狀態(tài)           console.log(val)       }, 1000)   }   return (       <>           <p>{val}</p>           <button onClick={()=>setVal(val+1)}>+</button>           <button onClick={timeoutFn}>alertNumber</button>       </>   ) }

當(dāng)組件的狀態(tài)或者props更新時(shí),該函數(shù)組件會被重新調(diào)用渲染,并且每一次的渲染都是獨(dú)立的都有自己獨(dú)立的props以及state,不會影響其他的渲染。

2、useEffect

語法

useEffect(() => {     //handler function...          return () => {         // clean side effect     } }, [//dep...])

useEffect接收一個(gè)回調(diào)函數(shù)以及依賴項(xiàng),當(dāng)依賴項(xiàng)發(fā)生變化時(shí)才會執(zhí)行里面的回調(diào)函數(shù)。useEffect類似于class組件didMount、didUpdate、willUnmount的生命周期函數(shù)。

注意點(diǎn)

  • useEffect是異步的在組件渲染完成后才會執(zhí)行

  • useEffect的回調(diào)函數(shù)只能返回一個(gè)清除副作用的處理函數(shù)或者不返回

  • 如果useEffect傳入的依賴項(xiàng)是空數(shù)組那么useEffect內(nèi)部的函數(shù)只會執(zhí)行一次

3、useMemo、useCallback

useMemo和useCallback主要用于減少組件的更新次數(shù)、優(yōu)化組件性能的。

  • useMemo接收一個(gè)回調(diào)函數(shù)以及依賴項(xiàng),只有依賴項(xiàng)變化時(shí)才會重新執(zhí)行回調(diào)函數(shù)。

  • useCallback接收一個(gè)回調(diào)函數(shù)以及依賴項(xiàng),并且返回該回調(diào)函數(shù)的memorize版本,只有在依賴項(xiàng)重新變化時(shí)才會重新新的memorize版本。

語法

const memoDate = useMemo(() => data, [//dep...]) const memoCb = useCallback(() => {//...}, [//dep...])

在優(yōu)化組件性能時(shí)針對class組件我們一般使用React.PureComponent,PureComponent會在shouldUpdate進(jìn)行一次錢比較,判斷是否需要更新;針對函數(shù)組件我們一般使用React.memo。但是在使用react hooks時(shí)由于每一次渲染更新都是獨(dú)立的(生成了新的狀態(tài)),即使使用了React.memo,也還是會重新渲染。

比如下面這種場景,改變子組件的name值后由于父組件更新后每次都會生成新值(addAge函數(shù)會改變),所以子組件也會重新渲染。

function Parent() {   const [name, setName] = useState('cc')   const [age, setAge] = useState(22)    const addAge = () => {     setAge(age + 1)   }    return (     <>       <p>父組件</p>       <input value={name} onChange={(e) => setName(e.target.value)} />       <p>age: {age}</p>       <p>-------------------------</p>       <Child addAge={addAge} />     </>   ) }  const Child = memo((props) => {   const { addAge } = props   console.log('child component update')   return (     <>       <p>子組件</p>       <button onClick={addAge}>click</button>     </>   ) })

使用useCallback優(yōu)化

function Parent() {   const [name, setName] = useState('cc')   const [age, setAge] = useState(22)    const addAge = useCallback(() => {     setAge(age + 1)   }, [age])    return (     <>       <p>父組件</p>       <input value={name} onChange={(e) => setName(e.target.value)} />       <p>age: {age}</p>       <p>-------------------------</p>       <Child addAge={addAge} />     </>   ) }  const Child = memo((props) => {   const { addAge } = props   console.log('child component update')   return (     <>       <p>子組件</p>       <button onClick={addAge}>click</button>     </>   ) })

只有useCallback的依賴性發(fā)生變化時(shí),才會重新生成memorize函數(shù)。所以當(dāng)改變name的狀態(tài)是addAge不會變化。

4、useRef

useRef類似于react.createRef。

const node = useRef(initRef)

useRef 返回一個(gè)可變的 ref 對象,其 current 屬性被初始化為傳入的參數(shù)(initRef)

作用在DOM上

const node = useRef(null) <input ref={node} />

這樣可以通過node.current屬性訪問到該DOM元素。

需要注意的是useRef創(chuàng)建的對象在組件的整個(gè)生命周期內(nèi)保持不變,也就是說每次重新渲染函數(shù)組件時(shí),返回的ref 對象都是同一個(gè)(使用 React.createRef ,每次重新渲染組件都會重新創(chuàng)建 ref)。

5、useReducer

useReducer類似于redux中的reducer。

語法

const [state, dispatch] = useReducer(reducer, initstate)

useReducer傳入一個(gè)計(jì)算函數(shù)和初始化state,類似于redux。通過返回的state我們可以訪問狀態(tài),通過dispatch可以對狀態(tài)作修改。

const initstate = 0; function reducer(state, action) {   switch (action.type) {     case 'increment':       return {number: state.number + 1};     case 'decrement':       return {number: state.number - 1};     default:       throw new Error();   } } function Counter(){     const [state, dispatch] = useReducer(reducer, initstate);     return (         <>           Count: {state.number}           <button onClick={() => dispatch({type: 'increment'})}>+</button>           <button onClick={() => dispatch({type: 'decrement'})}>-</button>         </>     ) }

6、useContext

通過useContext我們可以更加方便的獲取上層組件提供的context。

父組件

import React, { createContext, Children } from 'react' import Child from './child'  export const MyContext = createContext()  export default function Parent() {    return (     <div>       <p>Parent</p>       <MyContext.Provider value={{name: 'cc', age: 21}}>         <Child />       </MyContext.Provider>     </div>   ) }

子組件

import React, { useContext } from 'react' import { MyContext } from './parent'  export default function Parent() {   const data = useContext(MyContext) // 獲取父組件提供的context   console.log(data)   return (     <div>       <p>Child</p>     </div>   ) }

使用步驟

  • 父組件創(chuàng)建并導(dǎo)出context:export const MyContext = createContext()
  • 父組件使用providervalue提供值:<MyContext.provide value={{name: 'cc', age: 22}} />
  • 子組件導(dǎo)入父組件的context:import { MyContext } from './parent'
  • 獲取父組件提供的值:const data = useContext(MyContext)

不過在多數(shù)情況下我們都不建議使用context,因?yàn)闀黾咏M件的耦合性。

7、useLayoutEffect

useEffect 在全部渲染完畢后才會執(zhí)行;useLayoutEffect 會在 瀏覽器 layout之后,painting之前執(zhí)行,并且會柱塞DOM;可以使用它來讀取 DOM 布局并同步觸發(fā)重渲染。

export default function LayoutEffect() {   const [color, setColor] = useState('red')   useLayoutEffect(() => {       alert(color) // 會阻塞DOM的渲染   });   useEffect(() => {       alert(color) // 不會阻塞   })   return (       <>         <div id="myDiv" style={{ background: color }}>顏色</div>         <button onClick={() => setColor('red')}>紅</button>         <button onClick={() => setColor('yellow')}>黃</button>       </>   ) }

上面的例子中useLayoutEffect會在painting之前執(zhí)行,useEffect在painting之后執(zhí)行。

hooks讓函數(shù)組件擁有了內(nèi)部狀態(tài)、生命周期,使用hooks讓代碼更加的簡介,自定義hooks方便了對邏輯的復(fù)用,并且擺脫了class組件的this問題;但是在使用hooks時(shí)會產(chǎn)生一些閉包問題,需要仔細(xì)使用。

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
日韩欧美综合| 久久福利在线| 欧美日韩尤物久久| 天堂中文av在线资源库| 岛国av在线网站| 精品视频在线你懂得| 久久中文字幕一区二区| 日本一二区不卡| 成人羞羞视频播放网站| 欧美1级日本1级| 日韩专区欧美专区| 奇米777国产一区国产二区| 国产麻豆精品| 手机在线电影一区| 婷婷成人在线| 一级成人国产| 国产精品白丝久久av网站| 成人午夜亚洲| 久久精品主播| 亚洲神马久久| 亚洲精品乱码| 欧美精品成人| 国产一区视频在线观看免费| 视频一区视频二区中文字幕| 欧美影院精品| 亚洲伊人av| 西西人体一区二区| 69堂免费精品视频在线播放| 嫩草伊人久久精品少妇av杨幂 | 91福利精品在线观看| 国产精品99久久久久久董美香| 国产一区不卡| 国产二区精品| 在线免费观看亚洲| 欧美精品97| 99精品在线免费在线观看| 亚洲一区二区三区四区五区午夜| 日韩国产一区二| 久久久久久色| 黄色在线网站噜噜噜| 国产农村妇女精品一区二区| 国产精品毛片aⅴ一区二区三区| 日韩三区免费| 日本不卡在线视频| av资源亚洲| 亚洲制服欧美另类| 色乱码一区二区三区网站| 九色精品91| 国产日韩欧美| 一区二区自拍| 国内在线观看一区二区三区| aa亚洲婷婷| 精品五月天堂| 综合激情五月婷婷| 日韩欧美网址| 欧美亚洲色图校园春色| 特黄特色欧美大片| 麻豆精品新av中文字幕| 一本色道久久精品| 精品入口麻豆88视频| 亚洲影视一区| 亚洲成人av观看| 亚洲影院天堂中文av色| 蜜桃视频在线网站| 国产精品最新| 老司机精品久久| 国产91在线播放精品| 亚洲人成高清| 欧美精品一二| 成人精品视频| 国产欧美激情| 亚洲精品乱码日韩| 99综合视频| 久久久久午夜电影| 精品欧美日韩精品| 日韩成人在线看| 亚洲电影在线一区二区三区| 免费一区二区三区在线视频| 亚洲欧美日韩国产一区二区| 日本综合字幕| 卡一卡二国产精品| 97久久精品| 亚洲天堂av资源在线观看| 视频小说一区二区| 国产成人免费精品| 国产另类在线| 香蕉久久久久久| 日韩一级网站| 91精品蜜臀一区二区三区在线| 美女视频黄久久| 欧美一区自拍| 亚洲精品系列| 99国产精品视频免费观看一公开| 蜜桃成人精品| 国产精品xx| 久久成人av| 97久久中文字幕| 日本在线一区二区三区| 亚洲男女自偷自拍| 伊人久久亚洲热| 亚洲成人一区| 在线日韩一区| 欧美一区二区性| 亚洲精品一级二级| 日韩中文字幕高清在线观看| 风间由美中文字幕在线看视频国产欧美| 日韩av一二三| 亚洲精品乱码久久久久久蜜桃麻豆| 国产91一区| 婷婷国产精品| 不卡在线一区| 亚洲免费在线| 亚洲精品女人| 日韩综合一区二区| 日韩在线黄色| 中文字幕一区二区三区四区久久| 91精品一区二区三区综合| 久久精品成人| 久久人人88| 精品在线99| 激情91久久| 蜜臀久久99精品久久久久宅男| 激情欧美日韩一区| 免费久久久久久久久| 亚洲精品在线观看91| 免费国产自久久久久三四区久久| 九一成人免费视频| 美女久久一区| 日韩精品一区二区三区免费视频| 奇米亚洲欧美| 麻豆精品av| 日韩毛片视频| 免费视频亚洲| 在线精品一区| 国产午夜精品一区在线观看| 国产乱人伦精品一区| 精品丝袜久久| 久久久噜噜噜| 国产精品av久久久久久麻豆网| 亚洲精品va| 中文字幕中文字幕精品| 欧美日韩中出| a国产在线视频| 国产二区精品| 日韩高清一级| 欧美激情视频一区二区三区在线播放| 精品视频在线你懂得| 久久免费国产| 免费看的黄色欧美网站| 日韩国产高清在线| 精品视频国内| 国产在线成人| 日韩精品免费视频人成| 国产日本久久| 国产h片在线观看| 久久精品国产99久久| 爽好久久久欧美精品| 69堂精品视频在线播放| 国产精品99一区二区三| 黄色成人在线网址| 欧美在线看片| 激情亚洲影院在线观看| 亚洲欧美日本视频在线观看| 国产日韩视频| 99精品在线观看| 亚洲精品在线国产| 成人精品动漫一区二区三区| 黄色av一区| 日韩国产欧美三级| 日韩在线看片| 日韩国产在线观看| 欧美不卡高清一区二区三区| 蜜臀av亚洲一区中文字幕| 国产黄色一区| 欧美特黄一级| 精品三级久久久| 日本欧洲一区二区| 精品视频国产| 视频一区二区三区入口| 精品一区二区三区免费看| 欧美精品九九| 麻豆精品视频在线| 尤物精品在线| 国产伦精品一区二区三区千人斩 | 国产精品久久久久久久久免费高清 | 日韩精品五月天| 亚洲综合电影| 日韩欧美久久| 偷拍精品精品一区二区三区| 天海翼亚洲一区二区三区| 国产欧洲在线| 亚久久调教视频| 国产精品国产一区| 综合欧美精品| 久久精品在线| 欧美激情 亚洲a∨综合| 蜜臀久久99精品久久久久宅男| 日韩精品91| 国产精品mv在线观看| 另类av一区二区|