欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React中的Component組件詳解

 更新時間:2023年06月10日 10:43:58   作者:江擁羨橙  
本章節(jié),我們將一起探討 React 中類組件和函數(shù)組件的定義,不同組件的通信方式,以及常規(guī)組件的強化方式,幫助你全方位認(rèn)識 React 組件,從而對 React 的底層邏輯有進一步的理解,感興趣的朋友跟隨小編一起看看吧

一 前言

在 React 世界里,一切皆組件,我們寫的 React 項目全部起源于組件。組件可以分為兩類,一類是類( Class )組件,一類是函數(shù)( Function )組件。

本章節(jié),我們將一起探討 React 中類組件和函數(shù)組件的定義,不同組件的通信方式,以及常規(guī)組件的強化方式,幫助你全方位認(rèn)識 React 組件,從而對 React 的底層邏輯有進一步的理解。

二 什么是React組件?

想要理解 React 組件是什么?我們首先要來分析一下組件和常規(guī)的函數(shù)和類到底有什么本質(zhì)的區(qū)別。

/* 類 */
class textClass {
    sayHello=()=>console.log('hello, my name is alien')
}
/* 類組件 */
class Index extends React.Component{
    state={ message:`hello ,world!` }
    sayHello=()=> this.setState({ message : 'hello, my name is alien' })
    render(){
        return <div style={{ marginTop:'50px' }} onClick={ this.sayHello } > { this.state.message }  </div>
    }
}
/* 函數(shù) */
function textFun (){ 
    return 'hello, world'
}
/* 函數(shù)組件 */
function FunComponent(){
    const [ message , setMessage ] = useState('hello,world')
    return <div onClick={ ()=> setMessage('hello, my name is alien')  } >{ message }</div>
}

我們從上面可以清楚地看到,組件本質(zhì)上就是類和函數(shù),但是與常規(guī)的類和函數(shù)不同的是,組件承載了渲染視圖的 UI 和更新視圖的 setState 、 useState 等方法。React 在底層邏輯上會像正常實例化類和正常執(zhí)行函數(shù)那樣處理的組件。

因此,函數(shù)與類上的特性在 React 組件上同樣具有,比如原型鏈,繼承,靜態(tài)屬性等,所以不要把 React 組件和類與函數(shù)獨立開來。

接下來,我們一起著重看一下 React 對組件的處理流程。

對于類組件的執(zhí)行,是在react-reconciler/src/ReactFiberClassComponent.js中:

function constructClassInstance(
    workInProgress, // 當(dāng)前正在工作的 fiber 對象
    ctor,           // 我們的類組件
    props           // props 
){
     /* 實例化組件,得到組件實例 instance */
     const instance = new ctor(props, context)
}

對于函數(shù)組件的執(zhí)行,是在react-reconciler/src/ReactFiberHooks.js中

function renderWithHooks(
  current,          // 當(dāng)前函數(shù)組件對應(yīng)的 `fiber`, 初始化
  workInProgress,   // 當(dāng)前正在工作的 fiber 對象
  Component,        // 我們函數(shù)組件
  props,            // 函數(shù)組件第一個參數(shù) props
  secondArg,        // 函數(shù)組件其他參數(shù)
  nextRenderExpirationTime, //下次渲染過期時間
){
     /* 執(zhí)行我們的函數(shù)組件,得到 return 返回的 React.element對象 */
     let children = Component(props, secondArg);
}

從中,找到了執(zhí)行類組件和函數(shù)組件的函數(shù)。那么為了搞清楚 React 底層是如何處理組件的,首先來看一下類和函數(shù)組件是什么時候被實例化和執(zhí)行的?

在 React 調(diào)和渲染 fiber 節(jié)點的時候,如果發(fā)現(xiàn) fiber tag 是 ClassComponent = 1,則按照類組件邏輯處理,如果是 FunctionComponent = 0 則按照函數(shù)組件邏輯處理。當(dāng)然 React 也提供了一些內(nèi)置的組件,比如說 Suspense 、Profiler 等。

三 二種不同 React 組件

1 class類組件

類組件的定義

在 class 組件中,除了繼承 React.Component ,底層還加入了 updater 對象,組件中調(diào)用的 setState 和 forceUpdate 本質(zhì)上是調(diào)用了 updater 對象上的 enqueueSetState 和 enqueueForceUpdate 方法。

那么,React 底層是如何定義類組件的呢?

react/src/ReactBaseClasses.js

function Component(props, context, updater) {
  this.props = props;      //綁定props
  this.context = context;  //綁定context
  this.refs = emptyObject; //綁定ref
  this.updater = updater || ReactNoopUpdateQueue; //上面所屬的updater 對象
}
/* 綁定setState 方法 */
Component.prototype.setState = function(partialState, callback) {
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
}
/* 綁定forceupdate 方法 */
Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
}

如上可以看出 Component 底層 React 的處理邏輯是,類組件執(zhí)行構(gòu)造函數(shù)過程中會在實例上綁定 props 和 context ,初始化置空 refs 屬性,原型鏈上綁定setState、forceUpdate 方法。對于 updater,React 在實例化類組件之后會單獨綁定 update 對象。

|--------問與答---------|

問:如果沒有在 constructor 的 super 函數(shù)中傳遞 props,那么接下來 constructor 執(zhí)行上下文中就獲取不到 props ,這是為什么呢?

/* 假設(shè)我們在 constructor 中這么寫 */
constructor(){
    super()
    console.log(this.props) // 打印 undefined 為什么?
}

答案很簡單,剛才的 Component 源碼已經(jīng)說得明明白白了,綁定 props 是在父類 Component 構(gòu)造函數(shù)中,執(zhí)行 super 等于執(zhí)行 Component 函數(shù),此時 props 沒有作為第一個參數(shù)傳給 super() ,在 Component 中就會找不到 props 參數(shù),從而變成 undefined ,在接下來 constructor 代碼中打印 props 為 undefined 。

/* 解決問題 */
constructor(props){ 
    super(props)
}

|---------end----------|

為了更好地使用 React 類組件,我們首先看一下類組件各個部分的功能:

class Index extends React.Component{
    constructor(...arg){
       super(...arg)                        /* 執(zhí)行 react 底層 Component 函數(shù) */
    }
    state = {}                              /* state */
    static number = 1                       /* 內(nèi)置靜態(tài)屬性 */
    handleClick= () => console.log(111)     /* 方法: 箭頭函數(shù)方法直接綁定在this實例上 */
    componentDidMount(){                    /* 生命周期 */
        console.log(Index.number,Index.number1) // 打印 1 , 2 
    }
    render(){                               /* 渲染函數(shù) */
        return <div style={{ marginTop:'50px' }} onClick={ this.handerClick }  >hello,React!</div>
    }
}
Index.number1 = 2                           /* 外置靜態(tài)屬性 */
Index.prototype.handleClick = ()=> console.log(222) /* 方法: 綁定在 Index 原型鏈的 方法*/

上面把類組件的主要組成部分都展示給大家了。針對 state ,生命周期等部分,后續(xù)會有專門的章節(jié)進行講解。

|--------問與答---------|

問:上述綁定了兩個 handleClick ,那么點擊 div 之后會打印什么呢?

答:結(jié)果是 111 。因為在 class 類內(nèi)部,箭頭函數(shù)是直接綁定在實例對象上的,而第二個 handleClick 是綁定在 prototype 原型鏈上的,它們的優(yōu)先級是:實例對象上方法屬性 > 原型鏈對象上方法屬性。

|---------end----------|

對于 pureComponent 會在 React 渲染優(yōu)化章節(jié),詳細(xì)探討。

2 函數(shù)組件

ReactV16.8 hooks 問世以來,對函數(shù)組件的功能加以強化,可以在 function 組件中,做類組件一切能做的事情,甚至完全取締類組件。函數(shù)組件的結(jié)構(gòu)相比類組件就簡單多了,比如說,下面寫了一個常規(guī)的函數(shù)組件:

class Index extends React.Component{
    constructor(...arg){
       super(...arg)                        /* 執(zhí)行 react 底層 Component 函數(shù) */
    }
    state = {}                              /* state */
    static number = 1                       /* 內(nèi)置靜態(tài)屬性 */
    handleClick= () => console.log(111)     /* 方法: 箭頭函數(shù)方法直接綁定在this實例上 */
    componentDidMount(){                    /* 生命周期 */
        console.log(Index.number,Index.number1) // 打印 1 , 2 
    }
    render(){                               /* 渲染函數(shù) */
        return <div style={{ marginTop:'50px' }} onClick={ this.handerClick }  >hello,React!</div>
    }
}
Index.number1 = 2                           /* 外置靜態(tài)屬性 */
Index.prototype.handleClick = ()=> console.log(222) /* 方法: 綁定在 Index 原型鏈的 方法*/

注意:不要嘗試給函數(shù)組件 prototype 綁定屬性或方法,即使綁定了也沒有任何作用,因為通過上面源碼中 React 對函數(shù)組件的調(diào)用,是采用直接執(zhí)行函數(shù)的方式,而不是通過new的方式。

那么,函數(shù)組件和類組件本質(zhì)的區(qū)別是什么呢?

對于類組件來說,底層只需要實例化一次,實例中保存了組件的 state 等狀態(tài)。對于每一次更新只需要調(diào)用 render 方法以及對應(yīng)的生命周期就可以了。但是在函數(shù)組件中,每一次更新都是一次新的函數(shù)執(zhí)行,一次函數(shù)組件的更新,里面的變量會重新聲明。

為了能讓函數(shù)組件可以保存一些狀態(tài),執(zhí)行一些副作用鉤子,React Hooks 應(yīng)運而生,它可以幫助記錄 React 中組件的狀態(tài),處理一些額外的副作用。

四 組件通信方式

React 一共有 5 種主流的通信方式:

  • props 和 callback 方式
  • ref 方式。
  • React-redux 或 React-mobx 狀態(tài)管理方式。
  • context 上下文方式。
  • event bus 事件總線。

這里主要講一下第1種和第5種,其余的會在對應(yīng)章節(jié)詳細(xì)解讀。

① props 和 callback 方式

props 和 callback 可以作為 React 組件最基本的通信方式,父組件可以通過 props 將信息傳遞給子組件,子組件可以通過執(zhí)行 props 中的回調(diào)函數(shù) callback 來觸發(fā)父組件的方法,實現(xiàn)父與子的消息通訊。

父組件 -> 通過自身 state 改變,重新渲染,傳遞 props -> 通知子組件

子組件 -> 通過調(diào)用父組件 props 方法 -> 通知父組件。

/* 子組件 */
function Son(props){
    const {  fatherSay , sayFather  } = props
    return <div className='son' >
         我是子組件
        <div> 父組件對我說:{ fatherSay } </div>
        <input placeholder="我對父組件說" onChange={ (e)=>sayFather(e.target.value) }   />
    </div>
}
/* 父組件 */
function Father(){
    const [ childSay , setChildSay ] = useState('')
    const [ fatherSay , setFatherSay ] = useState('')
    return <div className="box father" >
        我是父組件
       <div> 子組件對我說:{ childSay } </div>
       <input placeholder="我對子組件說" onChange={ (e)=>setFatherSay(e.target.value) }   />
       <Son fatherSay={fatherSay}  sayFather={ setChildSay }  />
    </div>
}

效果

⑤event bus事件總線

當(dāng)然利用 eventBus 也可以實現(xiàn)組件通信,但是在 React 中并不提倡用這種方式,我還是更提倡用 props 方式通信。如果說非要用 eventBus,我覺得它更適合用 React 做基礎(chǔ)構(gòu)建的小程序,比如 Taro。接下來將上述 demo 通過 eventBus 方式進行改造。

import { BusService } from './eventBus'
/* event Bus  */
function Son(){
    const [ fatherSay , setFatherSay ] = useState('')
    React.useEffect(()=>{ 
        BusService.on('fatherSay',(value)=>{  /* 事件綁定 , 給父組件綁定事件 */
            setFatherSay(value)
       })
       return function(){  BusService.off('fatherSay') /* 解綁事件 */ }
    },[])
    return <div className='son' >
         我是子組件
        <div> 父組件對我說:{ fatherSay } </div>
        <input placeholder="我對父組件說" onChange={ (e)=> BusService.emit('childSay',e.target.value)  }   />
    </div>
}
/* 父組件 */
function Father(){
    const [ childSay , setChildSay ] = useState('')
    React.useEffect(()=>{    /* 事件綁定 , 給子組件綁定事件 */
        BusService.on('childSay',(value)=>{
             setChildSay(value)
        })
        return function(){  BusService.off('childSay') /* 解綁事件 */ }
    },[])
    return <div className="box father" >
        我是父組件
       <div> 子組件對我說:{ childSay } </div>
       <input placeholder="我對子組件說" onChange={ (e)=> BusService.emit('fatherSay',e.target.value) }   />
       <Son  />
    </div>
}

這樣做不僅達到了和使用 props 同樣的效果,還能跨層級,不會受到 React 父子組件層級的影響。但是為什么很多人都不推薦這種方式呢?因為它有一些致命缺點。

  • 需要手動綁定和解綁。
  • 對于小型項目還好,但是對于中大型項目,這種方式的組件通信,會造成牽一發(fā)動全身的影響,而且后期難以維護,組件之間的狀態(tài)也是未知的。
  • 一定程度上違背了 React 數(shù)據(jù)流向原則。

五 組件的強化方式

①類組件繼承

對于類組件的強化,首先想到的是繼承方式,之前開發(fā)的開源項目 react-keepalive-router 就是通過繼承 React-Router 中的 Switch 和 Router ,來達到緩存頁面的功能的。因為 React 中類組件,有良好的繼承屬性,所以可以針對一些基礎(chǔ)組件,首先實現(xiàn)一部分基礎(chǔ)功能,再針對項目要求進行有方向的改造、強化、添加額外功能。

基礎(chǔ)組件:

/* 人類 */
class Person extends React.Component{
    constructor(props){
        super(props)
        console.log('hello , i am person')
    }
    componentDidMount(){ console.log(1111)  }
    eat(){    /* 吃飯 */ }
    sleep(){  /* 睡覺 */  }
    ddd(){   console.log('打豆豆')  /* 打豆豆 */ }
    render(){
        return <div>
            大家好,我是一個person
        </div>
    }
}
/* 程序員 */
class Programmer extends Person{
    constructor(props){
        super(props)
        console.log('hello , i am Programmer too')
    }
    componentDidMount(){  console.log(this)  }
    code(){ /* 敲代碼 */ }
    render(){
        return <div style={ { marginTop:'50px' } } >
            { super.render() } { /* 讓 Person 中的 render 執(zhí)行 */ }
            我還是一個程序員!    { /* 添加自己的內(nèi)容 */ }
        </div>
    }
}
export default Programmer

效果:

我們從上面不難發(fā)現(xiàn)這個繼承增強效果很優(yōu)秀。它的優(yōu)勢如下:

  • 可以控制父類 render,還可以添加一些其他的渲染內(nèi)容;
  • 可以共享父類方法,還可以添加額外的方法和屬性。

但是也有值得注意的地方,就是 state 和生命周期會被繼承后的組件修改。像上述 demo 中,Person 組件中的 componentDidMount 生命周期將不會被執(zhí)行。

②函數(shù)組件自定義 Hooks

在自定義 hooks 章節(jié),會詳細(xì)介紹自定義 hooks 的原理和編寫。

③HOC高階組件

在 HOC 章節(jié),會詳細(xì)介紹高階組件 HOC 。

六 總結(jié)

從本章節(jié)學(xué)到了哪些知識:

  • 知道了 React 組件本質(zhì)——UI + update + 常規(guī)的類和函數(shù) = React 組件 ,以及 React 對組件的底層處理邏輯。
  • 明白了函數(shù)組件和類組件的區(qū)別。
  • 掌握組件通信方式。
  • 掌握了組件強化方式。

下一章節(jié),我們將走進 React 狀態(tài)管理 state 的世界中,一起探討 State 的奧秘。

到此這篇關(guān)于React中的Component組件詳解的文章就介紹到這了,更多相關(guān)React Component組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React組件的三種寫法總結(jié)

    React組件的三種寫法總結(jié)

    本文主要總結(jié)了React組件的三種寫法以及最佳實踐,具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • React項目動態(tài)修改主題顏色的方案

    React項目動態(tài)修改主題顏色的方案

    這篇文章主要介紹了React項目動態(tài)修改主題顏色的方案,文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2025-01-01
  • react配置webpack-bundle-analyzer項目優(yōu)化踩坑記錄

    react配置webpack-bundle-analyzer項目優(yōu)化踩坑記錄

    這篇文章主要介紹了react配置webpack-bundle-analyzer項目優(yōu)化踩坑記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • React手寫一個手風(fēng)琴組件示例

    React手寫一個手風(fēng)琴組件示例

    這篇文章主要為大家介紹了React手寫一個手風(fēng)琴組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • React函數(shù)組件與類的區(qū)別有哪些

    React函數(shù)組件與類的區(qū)別有哪些

    函數(shù)式組件的基本意義就是,組件實際上是一個函數(shù),不是類,下面這篇文章主要給大家介紹了關(guān)于React中函數(shù)組件與類的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • React事件綁定詳解

    React事件綁定詳解

    這篇文章主要為大家介紹了React事件綁定,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • React Native自定義標(biāo)題欄組件的實現(xiàn)方法

    React Native自定義標(biāo)題欄組件的實現(xiàn)方法

    今天講一下如何實現(xiàn)自定義標(biāo)題欄組件,我們都知道RN有一個優(yōu)點就是可以組件化,在需要使用該組件的地方直接引用并傳遞一些參數(shù)就可以了,這種方式確實提高了開發(fā)效率。對React Native自定義標(biāo)題欄組件的實現(xiàn)方法感興趣的朋友參考下
    2017-01-01
  • React?Hook?Form?優(yōu)雅處理表單使用指南

    React?Hook?Form?優(yōu)雅處理表單使用指南

    這篇文章主要為大家介紹了React?Hook?Form?優(yōu)雅處理表單使用指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • React 路由傳參的幾種實現(xiàn)方法

    React 路由傳參的幾種實現(xiàn)方法

    React中傳參方式有很多,通過路由傳參的方式也是必不可少的一種,本文主要介紹了React路由傳參的幾種實現(xiàn)方法,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • useEffect?返回函數(shù)執(zhí)行過程源碼解析

    useEffect?返回函數(shù)執(zhí)行過程源碼解析

    這篇文章主要為大家介紹了useEffect?返回函數(shù)執(zhí)行過程源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04

最新評論