国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

一步一步實現Vue的響應式(對象觀測)

2024-05-06 15:35:08
字體:
來源:轉載
供稿:網友

平時開發中,Vue的響應式系統讓我們不再去操作DOM,只需關心數據邏輯的處理,極大地降低了代碼的復雜度。而響應式系統也是Vue的核心,作為開發者有必要了解其實現原理!

簡易版

以watch為切入點

watch是平時開發中使用率非常高的功能,其目的是觀測一個數據,當數據變化時執行我們預先定義的回調。使用方式如下:

{ watch: {  obj(val, oldVal) {   console.log(val, oldVal);  } }}

上面觀測了Vue實例的obj屬性,當其值發生變化時,打印出新值與舊值。

因此,我們定義一個watch函數:

function watch (data, key, cb) { // do something}
    watch函數接收3個屬性,分別是 data: 被觀測對象 key: 被觀測的屬性 cb: 數據變化后要執行的回調

Object.defineProperty

既然要在數據變化后再執行回調,所以需要知道數據是什么時候被修改的,這就是Object.defineProperty的作用,其為數據定義了訪問器屬性。在數據被讀取時會觸發get,在數據被修改時會觸發set。

我們定義一個defineReactive函數,其用來將一個數據變成響應式的:

function defineReactive(data, key) { let val = data[key];  Object.defineProperty(data, key, {  configurable: true,  enumerable: true,  get: function() {   return val;  },  set: function(newVal) {   if (newVal === val) {    return;   }      val = newVal;  } });}

defineReactive函數為data對象的key屬性定義了get、set,get返回屬性key的值val,set中修改key的值為新值newVal。到目前為止,key屬性還是沒有什么特殊之處。

數據被修改會觸發set,那cb一定是在set中被執行。但set與cb之間好像并沒有什么聯系,所以我們來搭建一座橋梁,來構建兩者的聯系:

let target = null;

我們在全局定義了一個target變量,它用來保存cb的值,然后在set中調用。所以,cb什么時候被保存在target中?回到出發點,我們要調用watch函數來觀測data的key屬性,當值被修改時執行我們定義的回調cb,這就是cb被保存在target中的時機了:

function watch(data, key, cb) { target = cb;}

watch函數中target被修改了,但我要是再想調用watch函數一次,也就是說我想在data[key]被修改時,執行兩個不同的回調,又或者說,我想再觀測data的其它屬性,那該怎么辦?必須得在target被再次修改前,將其值保存到別處。因為,target是同個屬性的不同回調或不同屬性的回調所共有的。

我們有必要為key屬性建立一個私有的倉庫,來保存回調。其實defineReactive函數有一點特殊地方:函數內部定義了一個val變量,然后在get和set函數都使用了val變量,這形成一個閉包,defineReactive函數的作用域是key屬性私有的,這就是天然的私有倉庫了:

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 柳林县| 萍乡市| 高陵县| 仁怀市| 吴桥县| 汉阴县| 开化县| 深水埗区| 若羌县| 滨州市| 南和县| 仙居县| 台湾省| 延长县| 曲周县| 阿瓦提县| 阳谷县| 唐海县| 上思县| 桐柏县| 南京市| 平安县| 丹江口市| 达拉特旗| 扬中市| 岫岩| 呈贡县| 普陀区| 沈丘县| 祁东县| 道孚县| 玉门市| 叶城县| 泸定县| 临桂县| 淮滨县| 册亨县| 七台河市| 富川| 星座| 铁岭市|