Proxy實現vue MVVM實踐

2021-09-02 05:38:47 字數 2781 閱讀 4054

vueconf(2018hangzhou)大會剛剛過去,vue作者尤大大向我們展示了vue3.0的進展,並介紹vue3.0的一些改動,其中最令我期待的就是重寫資料監聽機制。

談起vue的雙向資料繫結,我們首先能想到的就是es5中object.defineproperty,利用重寫屬性的getset,我們可以完成資料劫持監聽,使用觀察者模式,在資料發生改變的時候,通知訂閱者更新狀態。

我們就針對observer觀察者部分寫了乙個簡易的**如下:

function observer (data) 

observer.prototype = )

},convert: function (key, val) ,

definereactive: function (data, key, val)

return val

},set: function (newval)

})}}

function observe (value, vm)

return new observer(value)

}複製**

以上**中我們定義了乙個observer建構函式,即觀察者。利用object.defineproperty我們將傳入物件的所有屬性(包含子屬性)全部進行資料監聽,並在get方法中,在訂閱器裡新增一條訂閱。一旦某屬性發生改變,通知到訂閱器。

dep訂閱器,compile指令,watcher訂閱者的**就不再分析,mvvm的總體結構可以由下圖看出

整個過程是乙個觀察者、訂閱器、訂閱者、指令器四部分的事情,各司其職。

proxy是es6中新增的建構函式,它可以理解為在目標物件之前架設一層「攔截」,外界對該物件的訪問,都必須通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾改寫。proxy原意是**,在這裡我們可以理解為「**」某些操作。

var obj = new proxy({}, `)

return reflect.get(target, key, receiver)

},set: function (target, key, value, receiver) `)

return reflect.set(target, key, value, receiver)

}})複製**

上面**對乙個空物件架設了一層攔截,我們可以在proxy的第二個引數中傳入乙個handler物件,物件中可以定義攔截行為。

getset中,我們都用到了reflectreflect物件與proxy物件一樣,也是es6位了操作物件而提供的新api。reflect物件的方法與proxy物件的方法一一對應,比如proxy方法攔截target物件的屬性賦值行為。它採用reflect.set方法將值賦值給物件的屬性,確保完成原有的行為,然後再部署額外的功能。

根據以上**我們寫一段測試**:

obj.text = 'hello world!' 

// proxy set text

var _text = obj.text

// proxy get text

複製**

利用以上proxy的一些特性,我們修改**如下:

function observe (value, vm) 

let dep = new dep()

return new proxy(value,

return reflect.get(target, key, receiver)

},set: function (target, key, value, receiver)

})}複製**

我們將傳入的物件直接替換為proxy物件,入參handlergetset中的新增訂閱者和通知訂閱器邏輯保持不變。

整個過程沒有做其他多餘的判斷,由於vue3.0還沒有發布,沒有實際原始碼可以借鑑,所以以上只是個人實現的簡單版本(完整**)。將整個mvvm運用到html中,以下是執行後的效果(沒做gif,湊合看吧):

放棄了object.defineproperty,基於 proxy 觀察者機制以滿足全語言覆蓋及更好的效能。加上其它方法的優化改動,vue3.0可以提速一倍/記憶體使用降低一半;

observer模組將可以單獨作為乙個庫來使用。

很遺憾的是,es6的proxy無法被轉譯為es5,所以它將不被ie所支援。對於這個問題,vue3.0將給出ie11的相容方案,即在ie11下,還是使用的object.defineproperty機制。

ecmascript 6 入門(阮一峰):es6.ruanyifeng.com/#docs/proxy

vue 3.0 更新計畫:更快,更小,讓開發者更輕鬆: www.oschina.net/news/101906…

為什麼proxy可以優化vue的資料監聽機制: juejin.im/post/5bfe33…

Vue MVVM框架實現原理

資料劫持 發布訂閱模式 遍歷data選項中的屬性,新增資料的觀測,執行observe的方法,使用object.defineproperty方法轉換為get和set方法,實現資料的劫持,並且新增乙個compiler方法,對每個元素節點進行判斷,如果是文字節點,根據指令模板去替換資料 當資料發生變化時,...

javascript實現proxy模式

script 模式 proxy 也是物件,他的目的就是為了節制 控制 對本體物件的訪問 extjs就採用了很多中 模式 圖書館 本體物件,例項化讀書館需要消耗很多的資源 var libraryinte ce new bh.inte ce libraryinte ce addbook findbook...

Proxy實現AOP切面程式設計

通過jdk的proxy 實現對業務類做簡單的aop實現 介面 userservice 包含的方法為切入點,會被 攔截 類 userserviceimpl 實現userservice介面 類 userservicefactory 工廠模式生成動態 類 myaspect 切面類,實現對切入點的操作 us...