當前位置:編程學習大全網 - 源碼下載 - 響應式原理(壹)

響應式原理(壹)

可能很多小夥伴之前都了解過 Vue.js 實現響應式的核心是利用了 ES5 的 Object.defineProperty ,這也是為什麽 ?Vue.js 不能兼容 IE8 及以下瀏覽器 的原因,我們先來對它有個直觀的認識。

? Object.defineProperty?方法會直接在壹個對象上定義壹個新屬性,或者修改壹個對象的現有屬性, 並返回這個對象,先來看壹下它的語法: obj 是要在其上定義屬性的對象; prop 是要定義或修改的屬性的名稱; descriptor 是將被定義或修改的屬性描述符。

比較核心的是?descriptor,它有很多可選鍵值,具體的可以去參閱它的 文檔 。這裏我們最關心的是 get 和 set ,get?是壹個給屬性提供的 getter 方法,當我們訪問了該屬性的時候會觸發 getter 方法;set?是壹個給屬性提供的 setter 方法,當我們對該屬性做修改的時候會觸發 setter 方法。

壹旦對象擁有了 getter 和 setter,我們可以簡單地把這個對象稱為 響應式對象 。那麽 Vue.js 把哪些對象變成了響應式對象了呢,接下來我們從源碼層面分析。

在 Vue 的初始化階段,_init?方法執行的時候,會執行?initState(vm)?方法,它的定義在?src/core/instance/state.js?中。

initState?方法主要是對 props、methods、data、computed?和?wathcer?等屬性做了初始化 操作。這裏我們重點分析 props 和 data ,對於其它屬性的初始化我們之後再詳細分析。

props?的初始化主要過程,就是 遍歷定義的?props?配置 。遍歷的過程主要做兩件事情:壹個是調用 defineReactive 方法 把每個?prop?對應的值變成響應式 ,可以通過?vm._props.xxx?訪問到定義?props?中對應的屬性( 代理 )。對於?defineReactive?方法,我們稍後會介紹;另壹個是通過?proxy?把?vm._props.xxx?的訪問代理到?vm.xxx?上,我們稍後也會介紹。

data?的初始化主要過程也是做兩件事,壹個是對定義 data?函數返回對象的遍歷 ,通過 proxy 把每壹個值?vm._data.xxx?都 代理 到?vm.xxx?上;另壹個是調用 observe 方法觀測整個?data?的變化,把?data?也變成響應式,可以通過?vm._data.xxx?訪問到定義?data?返回函數中對應的屬性,observe?我們稍後會介紹。

可以看到,無論是?props?或是?data?的初始化都是把它們變成響應式對象,這個過程我們接觸到幾個函數,接下來我們來詳細分析它們。

首先介紹壹下代理,代理的作用是把?props?和?data?上的屬性代理到?vm?實例上,這也就是為什麽比如我們定義了如下 props,卻可以通過 vm 實例訪問到它。

我們可以在?say?函數中通過?this.msg?訪問到我們定義在?props?中的?msg,這個過程發生在 proxy 階段:

proxy?方法的實現很簡單,通過?Object.defineProperty 把?target[sourceKey][key]?的讀寫變成了對?target[key]?的讀寫 。所以對於?props?而言,對?vm._props.xxx?的讀寫變成了?vm.xxx?的讀寫,而對於?vm._props.xxx?我們可以訪問到定義在?props?中的屬性,所以我們就可以通過?vm.xxx?訪問到定義在?props?中的?xxx?屬性了。同理,對於?data?而言,對?vm._data.xxxx?的讀寫變成了對?vm.xxxx?的讀寫,而對於?vm._data.xxxx?我們可以訪問到定義在?data函數返回對象中的屬性,所以我們就可以通過?vm.xxxx?訪問到定義在?data?函數返回對象中的?xxxx?屬性了。

observe?的功能就是用來監測數據的變化,它的定義在?src/core/observer/index.js?中:

observe?方法的作用就是給 非 VNode 的對象類型數據添加壹個?Observer ,如果已經添加過則直接返回,否則在滿足壹定條件下去實例化壹個?Observer?對象實例。接下來我們來看壹下?Observer?的作用。

Observer?的構造函數邏輯很簡單,首先實 例化?Dep?對象 ,這塊稍後會介紹,接著通過執行?def?函數 把自身實例添加到數據對象?value?的?__ob__?屬性上 ,def的定義在?src/core/util/lang.js?中:

回到?Observer?的構造函數,接下來會對?value?做判斷, 對於數組會調用?observeArray?方法,否則對純對象調用?walk?方法 。可以看到?observeArray?是遍歷數組再次調用?observe?方法,而?walk?方法是遍歷對象的 key 調用?defineReactive?方法,那麽我們來看壹下這個方法是做什麽的。

defineReactive?的功能就是 定義壹個響應式對象 ,給對象動態添加 getter 和 setter,它的定義在?src/core/observer/index.js?中:

defineReactive?函數最開始初始化?Dep?對象的實例,接著拿到?obj?的屬性描述符,然後 對子對象遞歸調用?observe?方法 ,這樣就保證了無論?obj?的結構多復雜,它的所有子屬性也能變成響應式的對象,這樣我們訪問或修改?obj?中壹個嵌套較深的屬性,也能觸發 getter 和 setter。最後利用?Object.defineProperty去給?obj?的屬性?key?添加 getter 和 setter。而關於 getter 和 setter 的具體實現,我們會在之後介紹。

  • 上一篇:如何找到個股的啟動點
  • 下一篇:微軟的歷史介紹下?
  • copyright 2024編程學習大全網