vue3雙向綁定實現(xiàn)原理解讀
一、vue3為什么要用proxy實現(xiàn)雙向綁定?
1.object.defineProperty的缺點
因為es5的object.defineProperty無法監(jiān)聽對象屬性的刪除和添加
不能監(jiān)聽數(shù)組的變化,除了push/pop/shift/unshift/splice/spObject.definert/reverse,其他都不行
Object.defineProperty只能遍歷對象屬性直接修改(需要深拷貝進(jìn)行修改)
2.proxy的優(yōu)點
>1、直接監(jiān)聽對象而非屬性
>2、直接監(jiān)聽數(shù)組的變化
>3、攔截的方式有很多種(有13種,set,get,has)
>4、Proxy返回一個新對象,可以操作新對象達(dá)到目的
3.proxy的缺點
1、proxy有兼容性問題
不能用polyfill來兼容(polyfill主要撫平不同瀏覽器之間對js實現(xiàn)的差異)
二、實現(xiàn)Vue3雙向綁定
<!DOCTYPE html> <html lang="en"> <head> ? ? <meta charset="UTF-8"> ? ? <meta http-equiv="X-UA-Compatible" content="IE=edge"> ? ? <meta name="viewport" content="width=device-width, initial-scale=1.0"> ? ? <title>Document</title> </head> <body> ? ? <div></div> ? ? <script> ? ? ? ? const toProxy = new WeakMap(); //存放的是代理后的對象 ? ? ? ? const toRaw = new WeakMap(); ? //存放的是代理前的對象 ? ? ? ? function trigger() { ? ? ? ? ? ? console.log('觸發(fā)視圖更新') ? ? ? ? } ? ? ? ? function isObject(target) { ? ? ? ? ? ? return typeof target === 'object' && target !== null; ? ? ? ? } ? ? ? ? function reactive(target) { ? ? ? ? ? ? if (!isObject(target)) { ? ? ? ? ? ? ? ? return target; ? ? ? ? ? ? } ? ? ? ? ? ? let proxy = toProxy.get(target) ? ? ? ? ? ? // 如果代理表中已經(jīng)存在了 ?就把這個結(jié)果返回 ? ? ? ? ? ? if (proxy) { ? ? ? ? ? ? ? ? return proxy ? ? ? ? ? ? } ? ? ? ? ? ? // 如果這個對象已經(jīng)被代理過了 ?就直接返回 ? ? ? ? ? ? if (toRaw.has(target)) { ? ? ? ? ? ? ? ? return target; ? ? ? ? ? ? } ? ? ? ? ? ? const handlers = { ? ? ? ? ? ? ? ? set(target, key, value, receiver) { ? ? ? ? ? ? ? ? ? ? if (target.hasOwnProperty(key)) { ? ? ? ? ? ? ? ? ? ? ? ? trigger() ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? return Reflect.set(target, key, value, receiver) ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? get(target, key, value, receiver) { ? ? ? ? ? ? ? ? ? ? const res = Reflect.get(target, key, receiver) ? ? ? ? ? ? ? ? ? ? if (isObject(target[key])) { ? ? ? ? ? ? ? ? ? ? ? ? return reactive(res) ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? return res; ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? deleteProperty(target, key) { ? ? ? ? ? ? ? ? ? ? return Reflect.deleteProperty(target, key) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? let observed = new Proxy(target, handlers) ? ? ? ? ? ? toProxy.set(target, observed); ? ? ? ? ? ? toRaw.set(observed, target) ? ? ? ? ? ? return observed ? ? ? ? } ? ? ? ? let obj = { ? ? ? ? ? ? name: '溫小鹿', ? ? ? ? ? ? arr: [1, 2, 3] ? ? ? ? } ? ? ? ? // let p = reactive(obj) ? ? ? ? // p.name = 'jw' ? ? ? ? // let arr = [1, 2 ,3]; ? ? ? ? // let p = reactive(arr) ? ? ? ? // p.push(4); ? ? ? ? // console.log(p) ? ? ? ? let p = reactive(obj) ? ? ? ? p = reactive(p) ? ? ? ? p = reactive(p) ? ? ? ? p.arr.push(4) ? ? ? ? console.log(p) ? ? </script> </body> </html>
害,基礎(chǔ)不扎實,復(fù)習(xí)一下
Reflect是ES6為操作對象而提供的新API,proxy對象的方法在rReflect上都能找到
new WeakMap() 是弱引用,在內(nèi)存不足的時候垃圾回收機制才會回收,可以作為緩存
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue項目中使用WebUploader實現(xiàn)文件上傳的方法
WebUploader是由 Baidu WebFE(FEX) 團(tuán)隊開發(fā)的一個簡單的以 HTML5為主 , FLASH為輔 的現(xiàn)代 文件上傳組件 。這篇文章主要介紹了在Vue項目中使用WebUploader實現(xiàn)文件上傳,需要的朋友可以參考下2019-07-07純前端使用Vue3上傳文件到minio文件服務(wù)器(粘貼可直接用)
vue是目前最流行的前端框架,下面這篇文章主要給大家介紹了關(guān)于純前端使用Vue3上傳文件到minio文件服務(wù)器的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04Vue3中如何使用Three.js詳解(包括各種樣例、常見場景、問題及解決方案)
Three.js是一個常見的需求,Three.js是一個用于在瀏覽器中創(chuàng)建和顯示動畫3D計算機圖形的JavaScript庫,這篇文章主要介紹了Vue3中如何使用Three.js的相關(guān)資料,包括各種樣例、常見場景、問題及解決方案,需要的朋友可以參考下2025-04-04解決element DateTimePicker+vue彈出框只顯示小時
這篇文章主要介紹了解決element DateTimePicker+vue彈出框只顯示小時,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03