亚洲 国产精品 日韩-亚洲 激情-亚洲 欧美 91-亚洲 欧美 成人日韩-青青青草视频在线观看-青青青草影院

千鋒教育-做有情懷、有良心、有品質的職業教育機構

手機站
千鋒教育

千鋒學習站 | 隨時隨地免費學

千鋒教育

掃一掃進入千鋒手機站

領取全套視頻
千鋒教育

關注千鋒學習站小程序
隨時隨地免費學習課程

當前位置:首頁  >  技術干貨  > 為什么react選擇了函數式組件(剖析原理)

為什么react選擇了函數式組件(剖析原理)

來源:千鋒教育
發布人:wjy
時間: 2022-06-06 11:54:00 1654487640

以下代碼,沒有使用模塊化的方式,使用的是CDN的方式。如果需要源代碼,請從這個地址下載:

```text
鏈接:https://pan.baidu.com/s/1s57mr5AE_ecWBFZ5TJTwqw  提取碼:f7x2
```

另外,這篇文章,主要是剖析**組件的初次渲染和重新渲染**。所以,其它部分不要太較勁。

為什么react選擇了函數式組件

### **一、react類組件和函數式組件重新渲染時的區別**

### **1、看現象:**

### **1)代碼(demo01)**

**類組件:**

```js
    // 1、類組件
    class ComClass extends React.Component {
        constructor(props) {
            super();
            this.props = props;
            console.log("類組件的構造函數被調用了");
        }

        render() {
            console.log("類組件的render被調用了");
            return (
            <div style={{ "backgroundColor": "pink" }}>
                    <h5 >我是類組件</h5>
                    <p>{this.props.name}</p>
                </div>
            );
        }
    }
```

**函數式組件:**

```js
     // 2、函數式組件
    function ComFn(props) {
        console.log("函數式組件的函數被調用了");
        return (               
            <div style={{ "backgroundColor": "skyblue" }}>
                <h5 >我是函數式組件</h5>
                <p>{props.name}</p>
            </div>
        );
    }

```

 

**使用組件:**

```js

    let name = "張三瘋";
    function changeName() {
        name = "張四瘋"
        renderDom();
    }

    function renderDom() {
        ReactDOM.render(
            <div>
                <button onClick={changeName} >修改</button>
                <ComClass name={name} /><br />
                <ComFn name={name} />
            </div>, document.getElementById("box"));
    }

    renderDom();

```

 

### **2)運行:**

2.1)初次運行時,我們發現在控制臺中打印的內容為:

```js
類組件的構造函數被調用了
類組件的render被調用了
函數式組件的函數被調用了
```

 

2.2)當點擊“修改”按鈕時,我們發現控制臺中打印的內容為:

```js
類組件的render被調用了
函數式組件的函數被調用了
```

 

### **3)總結(敲黑板,重點):**

1、類組件重新渲染時,只調用了render

2、函數式組件重新渲染時,會調用函數整個本身(哈哈,不調用它也不行啊)

 

### **2、看原理:**

### **1)用原生的方式剖析:**

函數式組件的剖析:

```js
標簽的方式使用函數式組件:
<ComFn name={name} />
基本上等價于:
{ComFn({name})} //組件的方式使用,就是在調用函數
```

類組件的剖析:

```js
標簽的方式使用類組件:
<ComClass name={name} /><br/>
等價于
{new ComClass({name}).render()}

但是
這樣改了后,初次渲染沒有問題。當點擊了“修改”按鈕時,不一樣了。
所以,類組件里,應該是把new ComClass({name})實例化出來的對象,記錄起來了。所以,應該等價于
1、定義一個對象,保存了new ComClass({name})
   //在react里對類組件對象進行了保存。
   let comObj = new {new ComClass({name});

2、在渲染時,只是調用了類組件的render函數。
   comObj.render();
```

即:最終代碼變成了如下:

### **2)代碼(demo02):**

類組件和函數式組件的代碼不用改變。

**使用組件**

```js
    let name  = "張三瘋";
    //此處保存了類組件的實例化對象(這個只是模擬實現,react內部并不是這么簡單)
    let comObj = new ComClass({name});
    function changeName(){
        name = "張四瘋";
        comObj.props = {name}
        renderDom();
    }

    function renderDom(){
        ReactDOM.render(
        <div>
            <button onClick={changeName} >修改數據</button>
            {/*此處用原生的方式使用組件*/}
            {comObj.render()}
            {ComFn({name})}
        </div>, document.getElementById("box"));
    }

    renderDom();
```

### **3)運行:**

3.1)、初次運行時,我們發現在控制臺中打印的內容為:

```js
類組件的構造函數被調用了
類組件的render被調用了
函數式組件的函數被調用了
```

3.2)、當點擊“修改”按鈕時,我們發現控制臺中打印的內容為:

```js
類組件的render被調用了
函數式組件的函數被調用了
```

 

> 運行結果和組件的方式一樣。

### **二、看看組件里使用定時器,并且,重新渲染組件**

### **1、看現象**

### **1)代碼(demo03):**

**類組件:**

```js
   // 1、類組件
    class ComClass extends React.Component {
        constructor(props) {
            super();
            this.props = props;
            console.log("類組件的構造函數被調用了");
        }

        showMessage = () => {
            //在顯示props時(通過this訪問props),props里的內容被改變了。
            console.log('類組件: ' + this.props.name);
        };

        handleClick = () => {
            // 分析問題:
            // 1、3秒鐘后調用函數(通過 this 的方式調用)
            setTimeout(this.showMessage, 3000);
        };


        render() {
            console.log("類組件的render被調用了");
            return (
                <div style={{ "backgroundColor": "pink" }}>
                    <h5 >我是類組件</h5>
                    <p>name:{this.props.name}</p>
                    <input type="button" value="調用帶著定時器的函數" onClick={this.handleClick} />
                </div>
            );
        }
    }   
```

**函數式組件:**

```js
// 2、函數式組件
    function ComFn(props) {
        console.log("函數式組件的函數被調用了");

        //這個是閉包:
        // 每調用一次父函數(ComFn),都會重新定義一個新的子函數。新的函數中保存著父函數新的形參
        const showMessage = () => {
            console.log('函數式組件: ' + props.name);
        };

        //這個是閉包:
        //每調用一次父函數(ComFn),都會重新定義一個新的子函數。新的函數中保存著父函數新的形參
        const handleClick = () => {
            setTimeout(showMessage, 3000);
        };
       
        return (
            <div style={{ "backgroundColor": "skyblue" }}>
                <h5 >我是函數式組件</h5>
                <p>name:{props.name}</p>
                {/*先點擊這個按鈕,調用,第一次定義的 showMessage和handleClick*/}
                <input type="button" value="調用帶著定時器的函數" onClick={handleClick} />
            </div>
        );
    }
```

**使用組件:**

```js
  let name = "張三瘋";
    function changeName() {
        name = "張四瘋"
        renderDom();
    }

    function renderDom() {
        ReactDOM.render(
            <div>
                <button onClick={changeName} >修改</button>
                <ComClass name={name} /><br />
                <ComFn name={name} />
            </div>, document.getElementById("box"));
    }

    renderDom();
```

為什么react選擇了函數式組件1

### **2)、運行:**

**2.1)類組件:**

點擊類組件的“調用帶著定時器的函數” 按鈕后,再點擊”修改“按鈕(**注意先后順序**)。我們發現了:界面上打印的和控制臺打印的是**一樣的**。這是**不對的**:因為,我點擊“調用帶著定時器的函數” 按鈕時,name的值是”張三瘋“,應該打印”張三瘋“

為什么react選擇了函數式組件2

**2.2)函數式組件:**

點擊類組件的“調用帶著定時器的函數” 按鈕后,再點擊”修改“按鈕(**注意先后順序**)。我們發現了:界面上打印的和控制臺里打印的**不一樣**,這是**對的**:因為,我點擊“調用帶著定時器的函數” 按鈕時,name的值是”張三瘋“,應該打印”張三瘋“

為什么react選擇了函數式組件3

### **3)總結**

原因何在?以下文字要細細的品,如果品不出來,就結合上面的代碼,再看看。

類組件:

當**類組件重新渲染**時,**只調用了render函數**。組件的this不變。等定時器到了時,讀取屬性的的值時,先通過this找到props。再通過props找到name。而此時,name的值,已經發生了變化。所以,自然讀到的是新值“張四瘋” ,這個應該好理解。

函數式組件:

(你必須對閉包是清楚的),當**函數式組件重新渲染**時,**調用了函數**(組件),那么在函數式組件里的 函數(showMessage,handleClick)就會被重新定義,新定義的函數保存著父函數(組件)的新的形參和局部變量。而我們點擊“調用帶著定時器的函數”時,調用的是 第一次定義的showMessage,handleClick(這兩個函數里保存了父函數(組件)第一次傳入的形參和局部變量)。

其實,上面的代碼中,已經做了注釋。我再次解釋后,如果不明白的話,看看下面的剖析原理的代碼。

 

### **2、看原理:**

### **1)用原生的方式剖析**

與第一大點的第二小點的“剖析原理”一樣:

函數式組件的剖析:

```js
標簽的方式使用函數式組件:
<ComFn name={name} />
基本上等價于:
{ComFn({name})} //組件的方式使用,就是在調用函數
```

類組件的剖析:

```js
把new ComClass({name})實例化出來的對象,記錄起來了。

1、定義一個對象,保存了new ComClass({name})
   //在react里對類組件對象進行了保存。
   let comObj = new {new ComClass({name});

2、在渲染時,只是調用了類組件的render函數。
   comObj.render();
```

### **2)代碼(demo04):**

類組件和函數式組件的代碼不用變(同第二大點的第一小點:組件里使用定時器,并重新渲染組件)。

**使用組件:**

這個代碼等同于第一大點的第二小點。

```js
 let name = "張三瘋";
    let comObj = new ComClass({ name });
    function changeName() {
        name = "張四瘋";
        comObj.props = { name }
        renderDom();
    }

    function renderDom() {       
        ReactDOM.render(
            <div>
                <button onClick={changeName} >修改</button>
                {comObj.render()}
                {ComFn({name})}
            </div>, document.getElementById("box"));
    }

    renderDom();

```

 

### **三、為什么react現在更推薦函數式組件**

為什么react選擇了函數式組件4

React的核心理念之一就是,**界面應當是數據的不同形式的簡單投影**。**相同的輸入應該產生相同的輸出**。而函數式組件的寫法,使用閉包的特性,顯然符合這一理念:每個閉包里保存在父函數的當前形參(props)和局部變量。而類組件里,由于,每次讀取數據,要根據this指針去讀取,那必然不會讀取到屬于自己當前狀態的值。而是更新后的最新的值。

 

### **四、補充:類組件如何解決以上問題呢:**

其實還是利用了閉包。

### **看類組件的代碼修改(demo05):**

 

```js
//修改類組件里的showMessage 和 handleClick 函數。

showMessage = (name) => {
    console.log('類組件: ' + name);
};

handleClick = () => {
    let name = this.props.name;
    //此處:
    //1 、()=>this.showMessage(name)是閉包。父函數是handleClick,
    //2、閉包會把當前的局部變量name持有,然后,調用 showMessage(name)時,把name的值傳入showMessge里
    setTimeout(()=>this.showMessage(name), 3000);
};

```

 

### **五、類組件和函數式組件區別:**

在react的模式和開發思維上,函數組件和類組件還是有區別的。

1、各自的特點:

1)類的組件主要是面向對象編程,是建立在繼承之上,它的生命周期等核心概念的特點  2)函數組件主要是函數式編程,無副作用,并且在引用的時候透明的特點

2、使用場景:

因為兩者主打的特點不一樣,所以在使用場景上自然就存在一些差異了: 如果組件依賴生命周期,并且它的設計上需要繼承的特性,我們在選擇上更傾向類組件會更合適一點

由于HOOK的推出,逐漸降低了生命周期的概念,那么函數組件可以更好的取代類組件的開發,而且官方也推崇“組合優于繼承”的思想,所以類組件的優勢也在慢慢的淡出。更多關于web培訓的問題,歡迎咨詢千鋒教育在線名師。千鋒教育擁有多年IT培訓服務經驗,采用全程面授高品質、高體驗培養模式,擁有國內一體化教學管理及學員服務,助力更多學員實現高薪夢想。

tags:
聲明:本站稿件版權均屬千鋒教育所有,未經許可不得擅自轉載。
10年以上業內強師集結,手把手帶你蛻變精英
請您保持通訊暢通,專屬學習老師24小時內將與您1V1溝通
免費領取
今日已有369人領取成功
劉同學 138****2860 剛剛成功領取
王同學 131****2015 剛剛成功領取
張同學 133****4652 剛剛成功領取
李同學 135****8607 剛剛成功領取
楊同學 132****5667 剛剛成功領取
岳同學 134****6652 剛剛成功領取
梁同學 157****2950 剛剛成功領取
劉同學 189****1015 剛剛成功領取
張同學 155****4678 剛剛成功領取
鄒同學 139****2907 剛剛成功領取
董同學 138****2867 剛剛成功領取
周同學 136****3602 剛剛成功領取
相關推薦HOT
日日摸夜夜添夜夜添影院| 久久综合噜噜激激的五月天| 久久精品亚洲日本波多野结衣| 老旺的大肉蟒进进出出视频| 欧洲精品99毛片免费高清观看| 色综合AV综合无码综合网站| 亚洲AV之男人的天堂网站| 中国老太婆BB无套内射| 成年午夜免费AⅤ在线观看| 国产免费一区二区三区在线观看| 久久国产亚洲AV无码麻豆 | 小辣椒AV福利在线网站| 亚洲孕妇精品无码av| 把腿张开老子臊烂你多P| 国产免费久久精品99久久| 久久人与动人物A级毛片| 日本一卡2卡3卡4卡| 亚洲成AV人片在线观看无码不卡| 8V蜜桃网最新电影| 国产精品无码一本二本三本色| 久久久久国产精品免费免费搜索| 日本VA欧美VA精品发布| 亚洲第一SE情网站| А∨天堂一区一本到| 国精产品一区一区三区M| 欧美 亚洲 国产 日韩 综AⅤ| 无码人妻精品内射一二三AV| 荫蒂每天被三个男人添视频| 丰满多毛的大隂户毛茸茸| 久久精品丝袜高跟鞋| 日韩乱码人妻无码中文字幕视频| 亚洲精品TV久久久久久久久久| WWW国产亚洲精品久久麻豆| 国内AI明星造梦鞠婧祎MV| 欧美性猛交一区二区三区精品| 久久AV无码精品人妻出轨| 高清不卡亚洲日韩AV在线| 高潮久久久久久久久不卡| 久久久久精品日韩久久久| 日日猛噜噜狠狠扒开双腿小说| 亚洲国产成人久久综合一区77 | 久久久久人妻精品一区二区三区| 色一情一乱一伦一视频免费看| 野花新免费高清完整在线观看| 国产99视频精品免费视频6| 老师在办公室被躁在线观看| 天天躁夜夜躁很很躁| 14萝自慰专用网站| 国内偷窥一区二区三区视频| 人妻丰满熟妇AV无码区动漫| 亚洲手机看片AV| 够了够了到高C了| 免费A级毛片无码免费视频首页| 小寡妇好紧进去了好大看视频| AV无码一区二区大桥未久| 精品少妇人妻AV一区二区三区| 色噜噜亚洲精品中文字幕| 最新中文字幕AV专区| 激情偷乱人伦小说免费看| 肉丝超薄少妇一区二区三区| 中文字幕人妻中文AV不卡专区| 韩国乱码片免费看| 少妇被 到高潮喷出白浆av| 最新版天堂资源网在线种子| 韩国电影理伦片完整| 少妇精品久久久久www| 51久久精品人人搡人人玩| 精品人妻AV一区二区三区不卡| 体型差糙汉乖乖女| A亚洲VA欧美VA国产综合| 久久久精品无码中文天美| 性 偷窥 间谍 tube| 赤裸羔羊Ⅲ致命快感 电影| 妺妺窝人体色www人体| 亚洲欧美日韩中文字幕在线一区 | 巨大黑人一级毛片| 亚洲AV综合色区无码二区偷拍| 国产SP调教打屁股视频网站| 欧美性受XXXX黑人XYX性爽| 樱花YY私人在线影院| 激情综合五月丁香五月激情| 无码天堂亚洲国产AV久久| 豆国产93在线 | 亚洲| 欧日韩无套内射变态| 中文无码制服丝袜人妻AV| 久久99精品久久久久久HB无码| 亚洲AⅤ永久无码中文字幕| 国产V亚洲V天堂A无码| 人与善交XUANWEN18| 99RE热这里只有精品| 浪货两个都满足不了你| 亚洲人成网站999久久久综合| 国产一区在线观看二区| 无码国模大尺度视频在线观看 | 日韩精品无码AV中文无码版| AV在线播放网站| 免费人成视频XVIDEOS| 永久免费的啪啪网站免费观看浪潮| 激情影院内射美女| 亚洲AV无码国产精品麻豆天美 | 久久精品国产精品国产一区| 亚洲H成年动漫在线观看网站| 国产片AV国语在线观麻豆| 天堂А√在线中文在线| 成人一区二区免费视频| 人妻少妇精品无码专区漫画 | 女人大胆张开荫道口∞| 宅男666在线永久免费观看| 久久天天躁夜夜躁狠狠2018| 亚洲一区二区三区乱码AⅤ蜜桃女 亚洲一区二区三区乱码AⅤ蜜桃 | 尿眼PEEHOLE重口| 最新日本一道免费一区二区| 免费A级毛片无码A∨奶水在线| 中文无码日韩欧免费视频| 老头挺进娇妻身体| 中国97在线 | 免费| 蜜臀av一区二区三区久久 | 免费国产VA在线观看中文字| 中国丰满少妇性BBBBBBBB| 乱码人妻Av一区二区三区| 在线无码一区二区| 免费女同毛片在线播放| 60老熟女多次高潮露脸视频| 女M羞辱调教视频网站| FREE性丰满白嫩白嫩的HD| 青草久久久国产线免费| 啊灬啊灬啊灬快高潮了网站| 日本老熟妇VIDEO| 丰满人妻无码AⅤ一区二区| 天天躁日日躁狠狠躁AV中文| 国产老妇伦国产熟女老妇高清| 亚洲 欧美 国产 制服 动漫| 狠狠狠的在啪线香蕉WWW、WL| 亚洲区色情区激情区小说色情书| 久久久久亚洲AV无码观看 | 亚洲国产成人精品无码区在线秒播| 精品无码AV一区二区三区少妇| 一本大道香蕉在线精品| 男女做高潮120秒试看| 凹凸在线无码免费视频| 少妇大叫太大太爽受不了| 国产美女遭强高潮开双腿| 亚洲不卡无码永久在线| 久久青青草原亚洲AV无码| 18禁美女裸体无遮挡免费观看国 | HUGEBOOBS熟妇大波霸| 搡老女人熟妇老太HD| 国产精品毛片久久久久久久| 亚洲国产精品不卡AV在线| 旧芭乐视频官网下载地址IOS| 99热精品国产三级在线| 色哟哟在线视频精品一区| 国产精品无码一区二区三区电影| 亚洲成人AV一区二区| 美女扒开尿口让男人桶| 宝贝乖女小芳小雪| 无码免费大香伊蕉在人线国产| 寂寞骚妇被后入式爆草抓爆| 在线观看内射亲妹妹无套内射| 强被迫伦姧在线观看无码| 国产成人精品一区二区视频| 亚洲成人无码AV| 免费无遮挡很爽很污很黄的网站| 超碰AⅤ人人做人人爽| 小货SAO边洗澡边CAO你动漫| 久久久人人人婷婷色东京热| S货叫大点声C烂你的SB视频| 无码精品人妻一区二区三区漫画| 精品无码国产自产拍在线观看蜜桃| 综合色一色综合久久网| 色欲av夜夜嗨av性色av| 国内精品视频在线观看九九| 中文字幕乱理片人妻无码888| 日文文本乱码高清| 好大好硬好深好爽想要20P| 19岁MACBOOKPRO免费| 特黄AAAAAAAAA毛片免费| 精品无码国产自产在线观看水浒传| 91夜色精品偷窥熟女精品网站 | 欧美一区二区三区啪啪| 国产精品香蕉成人网在线观看 | 成人欧美一区二区| 亚洲精品无码一区二区AⅤ污| 欧美人与禽XOXO牲伦交| 国产精品亚洲VA在线| 中国女人黑森林毛耸耸| 双腿吊起揉捏花蒂| 久久亚洲精品无码爱剪辑| 大陆极品少妇内射AAAAAA| 亚洲精品成人福利网站| 人妻精品一区二区三区蜜桃| 国内精品久久久久精品| AV人摸人人人澡人人超碰下载| 午夜精品一区二区三区免费视频| 美女内射在线观看| 国产精品狼人久久久久影院| 18禁无遮挡羞羞啪啪免费网站| 无人区码一码二码三码区| 男女无遮挡猛进猛出免费观看视频| 国产精品欧美福利久久|