<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          記一次比較Vue2和Vue3響應(yīng)式原理和性能差異

          共 5005字,需瀏覽 11分鐘

           ·

          2021-03-02 12:48


          關(guān)注公眾號 前端人,回復(fù)“加群

          添加無廣告優(yōu)質(zhì)學(xué)習(xí)群

          寫在前面

          Vue響應(yīng)式原理是數(shù)據(jù)驅(qū)動視圖的核心,它能夠自動幫助開發(fā)者監(jiān)聽數(shù)據(jù)的變化,最終觸發(fā)視圖更新。它是Vue的渲染更新過程的核心。

          那么了解這一部分的原理至關(guān)重要,這篇文章就結(jié)合vue2和vue3響應(yīng)式來做一個對比,既明白了響應(yīng)式原理的實現(xiàn),又對比了二者在性能上的差異~

          需要了解的api

          這篇文章不是零基礎(chǔ),需要對一些基礎(chǔ)api有一定的了解,那么這里給出這些api的官方文檔,供大家參考學(xué)習(xí):

          • vue2響應(yīng)式原理
          • Object.defineProperty
          • vue3響應(yīng)式原理
          • Proxy
          • Reflect

          準(zhǔn)備一個原始對象數(shù)據(jù)

          為了做這個實驗,我使用同一個數(shù)據(jù)對象來分別做vue2和vue3的示例:注意這個data數(shù)據(jù)從最外層花括弧到最里層總共8個層級,你可以數(shù)一下。

          const data = {
              username'tom',
              profile: {
                  city'beijing',
                  a: {
                      b12,
                      c: {
                          d23
                      }
                  }
              }
          }

          接下來我分別寫點代碼對這個數(shù)據(jù)做響應(yīng)式處理:

          vue2

          const data = {
            username"tom",
            profile: {
              city"beijing",
              a: {
                b12,
                c: {
                  d23,
                },
              },
            },
          };
          function observe(data{
            console.log(1);
            if (typeof data !== "object" || data == null) {
              return data;
            }
            for (const key in data) {
              defineReactive(data, key, data[key]);
            }
          }

          function defineReactive(target, key, val{
            observe(val);
            Object.defineProperty(target, key, {
              get() {
                console.log(`get ${key}`);
                return val;
              },
              set(newValue) {
                console.log(`set ${key}`);
                if (newValue !== val) {
                  observe(newValue);
                  val = newValue;
                }
              },
            });
          }
          observe(data);
          console.log(data);

          打印的結(jié)果如下:

          從圖中可以清晰的看到總共打印了8次1,也就是說observe一共執(zhí)行了8次;由此可見vue2是一次遞歸到底的來實現(xiàn)響應(yīng)式的,好接下來看看vue3:

          vue3

          function observe(data{
            console.log(1);
            if (typeof data !== "object" || data == null) {
              return data;
            }
            const p = new Proxy(data, {
              get(target, key, receiver) {
                console.log(`get ${key}`);
                const result = Reflect.get(data, key, receiver);
                // 當(dāng)獲取值的是時候 再設(shè)置響應(yīng)式
                return observe(result);
              },
              set(target, key, val, receiver) {
                console.log(`set ${key}`);
                const result = Reflect.set(target, key, val, receiver);
                return result;
              },
            });
            return p;
          }

          const data = {
            username"tom",
            profile: {
              city"beijing",
              a: {
                b12,
                c: {
                  d23,
                },
              },
            },
          };

          const p1 = observe(data);
          console.log(p1);

          打印結(jié)果如圖:

          只打印了一次1,也就是說observe只執(zhí)行了一次,從代碼可以看出,將來執(zhí)行g(shù)et的時候,observe又會再次執(zhí)行。什么意思呢?也就是說Vue3對于數(shù)據(jù)的深層監(jiān)聽只有當(dāng)獲取值的時候才會響應(yīng)式處理,這樣在性能上肯定會提升很多。爭議

          讀到這里,拋開其他細(xì)節(jié)來講,可能你會來句臥槽,那Vue2也可以在get的時候observe啊,確實如此,但是想一下是不是會有點問題呢?問題就在于每次執(zhí)行g(shù)et的時候,不管是獲取哪個屬性,都需要執(zhí)行一下observe,并且它還是會向下遍歷,這樣增加了時間復(fù)雜度,可想而之,其性能是多么浪費的,還不如一次性深度監(jiān)聽到底呢?

          而proxy則不一樣,它只會響應(yīng)式處理你get的那個層級,它不會深度遍歷,這樣解釋你明白了嗎?

          總結(jié)

          接下來總結(jié)一下二者響應(yīng)式的差異

          • Object.defineProperty
          1. 深度監(jiān)聽,性能問題
          2. 新增刪除屬性問題,這個可以參考我前面寫的一個文章總結(jié)一下Vue那些常用必會面試必考的API,這里說明了vue2為什么需要set&delete兩個api
          3. 數(shù)組問題,需要重寫數(shù)組原型的幾個方法
          • Proxy
          1. 性能提升了一大截
          2. 解決了vue2的那些問題
          3. 兼容性有待處理

          當(dāng)然示例代碼都沒做優(yōu)化,實際上源碼肯定是對各種情況還做了處理,這里就不做介紹了,可以自己去看源碼哈~如果你對本文有什么看法或者覺得不對的地方,請在評論區(qū)賜教!共勉進(jìn)步~~

          原文:juejin.cn/post/6933953813657157646


          • 回復(fù)資料包領(lǐng)取我整理的進(jìn)階資料包
          • 回復(fù)加群,加入前端進(jìn)階群
          • console.log("點贊===看===你我都快樂"
          • Bug離我更遠(yuǎn)了,快樂離我更近了
          瀏覽 116
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  特级做a爰片毛片免费69 | 黑人JiZZ10性黑人 | 青青草青青在线视频播放 | 又黄又爽的美女裸体视频十八禁亚洲 | 伊人青青亚洲 |