成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

揭秘!Vue3.5響應式重構如何讓內存占用減少56%

開發 前端
Vue3.5響應式重構主要是通過雙向鏈表和版本計數?實現的,優化后內存占用減少了56%。主要原因是:在新的響應式系統中多了一個Link節點?用于鏈接Sub訂閱者和Dep依賴?,更新Sub訂閱者依賴只是進行指針的變換,并且還能夠復用Link節點?以及將不再使用的Link節點給孤立出來便于V8更快的將這個Link節點給回收。

前言

Vue3.5版本又將響應式給重構了,重構后的響應式系統主要有兩部分組成:雙向鏈表和 版本計數。我們在前兩篇文章中我們已經講過了 雙向鏈表和 版本計數,這篇文章我們來講講為什么這次重構能夠讓內存占用減少56%。

為什么說“又”將響應式重構了

因為在之前的Vue3.4版本中剛剛將響應式給重構了,這次響應式重構是vscode插件Vue-Official(原名Volar)的作者Johnson Chu搞的。

3.4版本的重構優化了很多東西,最直觀的就是:computed計算屬性的值沒有變化,另外一個watch又監聽了這個computed的值。在3.4以前還是會觸發watch的回調,經過3.4的優化后就不會觸發了。

在3.5版本以前,Vue的響應式系統中有兩個角色:Sub訂閱者和Dep依賴。

Sub訂閱者:主要有watchEffect、watch、render函數、computed等。

Dep依賴:主要有ref、reactive、computed等響應式變量。

他們兩之間是相互依賴的關系,如下圖:

圖片圖片

Dep依賴(比如ref響應式變量)可以通過dep屬性訪問到Sub訂閱者(比如computed計算屬性),就知道了到底有哪些訂閱者依賴自己,當自己的值改變后就能去通知訂閱者。

同樣Sub訂閱者(比如computed計算屬性)可以通過deps屬性訪問到Dep依賴(比如ref響應式變量),當Sub訂閱者不再依賴某個變量時就可以通過這個關系去訪問到這個Dep依賴。然后把自己從不再依賴的變量的Sub訂閱者集合中去掉,這樣當這個響應式變量改變后就不會通知到不再訂閱到他的Sub訂閱者了。

我們來看個例子,代碼如下:

<template>
  <p>{{ doubleCount }}</p>
  <button @click="flag = !flag">切換flag</button>
</template>

<script setup>
import { computed, ref } from "vue";
const count1 = ref(1);
const count2 = ref(10);
const flag = ref(true);

const doubleCount = computed(() => {
  console.log("computed");
  if (flag.value) {
    return count1.value * 2;
  } else {
    return count2.value * 2;
  }
});
</script>

當flag的值為true時計算屬性doubleCount其實只依賴響應式變量flag和count1,當flag的值切換為false時,計算屬性應該變成依賴變量flag和count2。

就上面這個更新Sub訂閱者依賴的邏輯,Vue其實重構了很多次。在早期的Vue3版本中是直接清空Sub訂閱者所依賴的響應式變量,然后再重新執行計算屬性doubleCount時再去將新的響應式變量進行收集。很明顯這個版本內存的使用就非常浪費了。

在最新的Vue3.4版本重構后的響應式系統中會在執行計算屬性之前利用_trackId和_depsLength字段進行標記,在重新執行計算屬性時進行依賴收集就可以利用_trackId和_depsLength字段判斷出Dep依賴是否能夠復用,并且執行完計算屬性的回調函數后同樣利用_trackId和_depsLength字段就可以將不再依賴的Dep依賴給移除掉。

上面這個方案看著很完美,但是他的核心是依賴計算屬性中所依賴的變量順序不變,如果順序變了,那么依然還是不能夠復用的,同樣會對浪費內存。(PS:這一段3.4版本響應式看不懂沒關系,因為他已經是過去式了)

內存優化主要原因:復用Link節點

在Vue3.5版本中那個最了解Vue的男人出手了,使用雙向鏈表和版本計數將響應式系統再次給重構了。說實話這次重構后讓讀響應式源碼的門檻變得更高了,但是收益特別明顯,最主要是通過復用Link節點去實現減少內存的使用。

還是上面的那個例子,對應新的響應式模型如下圖:

圖片圖片

在新的響應式模型中Sub訂閱者和Dep依賴之間不再有直接的關聯關系了,而是通過中間的Link節點作為橋梁去關聯。

在前一節中我們講過了,3.5以前Sub訂閱者中有屬性會去存依賴的Dep依賴,Dep依賴中有屬性去存依賴他的Sub訂閱者,所以導致當Sub訂閱者依賴的變量需要更新時就無法做到完全的復用,內存就會浪費。

如果下面的內容你看不懂,這不是你理解力有問題,原因是你對雙向鏈表不熟悉,可以先看看我之前的 雙向鏈表文章。

在3.5新的響應式模型中,X軸是Dep依賴,Y軸是Sub訂閱者,Link節點是作為坐標軸上面的點。每一組Dep依賴和Sub訂閱者都會對應一個Link節點,并且可以通過這個Link節點直接訪問到Dep依賴和Sub訂閱者。

在Y軸上面找一個點(比如Sub1也就是計算屬性doubleCount),橫向出發就可以找到Sub1訂閱者所依賴的所有響應式變量。因為橫向的這些Link節點是一個雙向鏈表,并且可以通過某一個Link節點直接訪問到他的Dep依賴。

當flag的值切換為false后,訂閱者Sub1所依賴的響應式變量就從flag+count1變成flag+count2。這時我們需要做的事情就很簡單了,新建一個Link3節點,可以直接訪問到Sub1和Dep3。然后將Link1中原本指向Link2的指針改為指向Link3,同時讓Link3的指針也指向Link1。并且將Link2指向Link1的指針改為指向空,由于Dep2現在不被任何訂閱者所依賴了,所以將Link2原本指向Dep2的指針也改為指向空,同樣將Dep2指向Link2的指針也指向空。

上面的一頓操作,除了必要的初始化一個Link3之外我們一直都是在進行指針的操作,并不像以前的響應式一樣去增加Sub訂閱者依賴或者減少依賴,這是非常高效的方式。

當flag的值切換為false后,新的響應式模型圖如下:

圖片圖片

從上圖中可以看到Link2已經徹底從雙向鏈表中移除了,并且整個過程中我們都是在操作指針的指向,所以Link1也一直都是復用的。

V8在進行垃圾回收的時候發現Link2不再被任何變量所使用,就可以認為Link2是一個可以被回收的變量,就會將其直接回收釋放內存。

Link節點復用以及讓不再使用的Link節點盡快的被回收進而釋放內存,就是這次響應式重構減少56%內存占用的主要原因。

其他優化

有了雙向鏈表后依賴觸發也變得更加清晰了,當某個響應式變量改變后,只需要遍歷Dep依賴(縱向)的Link節點組成的雙向鏈表,然后通過這些Link節點直接訪問到對應的Sub訂閱者,觸發其依賴。

基于此Sub訂閱者的觸發就是一個線性的過程,所以就可以實現將需要觸發的Sub訂閱者串起來組成了一個Sub訂閱者組成的隊列。等需要觸發的訂閱者收集完了后,再去進行觸發Sub訂閱者,避免同一個訂閱者被觸發多次。

依賴觸發相比之前也變得更加簡單了,性能以及內存也有所提升。

最后就是因為有了雙向鏈表和版本計數的加持后,computed計算屬性變得更加聰明,現在是惰性計算了。computed計算屬性只有等有人使用他(比如在template中使用計算屬性doubleCount)后才會去執行計算屬性中的回調函數,以及3.4版本中就已經實現的如果計算屬性值沒有變化,另外一個watch又監聽了這個computed的值,此時這個watch不會被觸發。關于這個可以看我之前的版本計數文章。

總結

Vue3.5響應式重構主要是通過雙向鏈表和版本計數實現的,優化后內存占用減少了56%。主要原因是:在新的響應式系統中多了一個Link節點用于鏈接Sub訂閱者和Dep依賴,更新Sub訂閱者依賴只是進行指針的變換,并且還能夠復用Link節點以及將不再使用的Link節點給孤立出來便于V8更快的將這個Link節點給回收。此外還有Sub訂閱者的觸發也變得更加簡單,以及現在是computed計算屬性是惰性計算了,這些優化同樣也優化了內存的使用。

責任編輯:武曉燕 來源: 前端歐陽
相關推薦

2024-11-06 10:47:53

2024-10-14 12:56:28

2024-09-04 11:42:17

Vue3.5源碼API

2024-09-02 08:48:45

2025-05-15 08:10:00

Vue 3.5Vue

2025-05-29 01:55:00

Vue3.5API性能

2024-09-05 09:17:14

2024-07-11 09:00:13

2010-10-28 15:15:08

oracle內存參數

2025-02-17 08:58:06

2020-07-14 08:32:49

VuelocalStorag響應式

2011-08-17 10:53:16

Firefox 7

2020-06-09 11:35:30

Vue 3響應式前端

2019-07-01 13:34:22

vue系統數據

2021-01-22 11:47:27

Vue.js響應式代碼

2021-03-12 19:26:54

ChromeChrome瀏覽器瀏覽器

2023-12-06 07:43:56

Vue如何定義事件

2021-05-19 14:25:19

前端開發技術

2017-08-30 17:10:43

前端JavascriptVue.js

2021-12-02 05:50:35

Vue3 插件Vue應用
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91色综合 | 一区二区三区视频免费看 | 中文字幕成人在线 | 国产性网| 在线黄色影院 | 成人国产精品色哟哟 | 精品欧美乱码久久久久久 | 久久久久久亚洲精品 | 成人性视频免费网站 | 色婷婷综合成人av | wwww.8888久久爱站网 | 成人在线视频免费观看 | 久久久久亚洲 | 成人免费日韩 | 亚洲免费在线视频 | 成人性生交大免费 | 国产精品乱码一区二区三区 | 精品国产乱码久久久久久a丨 | 99热精品在线 | 国产精品视频97 | 久久亚| 毛片入口| 精品在线看| 欧美综合自拍 | 精品国产99 | 亚洲免费毛片 | 亚洲欧美在线一区 | 精品视频在线免费观看 | 97人人澡人人爽91综合色 | 国产大毛片 | av在线一区二区三区 | 97视频网站 | 国产精品完整版 | 国内自拍真实伦在线观看 | 一区二区三区四区日韩 | 欧美一区二区三区一在线观看 | 亚洲精品久久久久久国产精华液 | 日本高清视频在线播放 | 日本又色又爽又黄的大片 | 在线免费av电影 | 国产成人在线视频播放 |