這篇文章主要介紹Vue3.0中Proxy怎么用,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),岳陽縣企業(yè)網(wǎng)站建設(shè),岳陽縣品牌網(wǎng)站建設(shè),網(wǎng)站定制,岳陽縣網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,岳陽縣網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。什么是 Proxy?
MDN 上是這么描述的——Proxy對象用于定義基本操作的自定義行為(如屬性查找,賦值,枚舉,函數(shù)調(diào)用等)。
官方的描述總是言簡意賅,以至于不明覺厲...
其實就是在對目標對象的操作之前提供了攔截,可以對外界的操作進行過濾和改寫,修改某些操作的默認行為,這樣我們可以不直接操作對象本身,而是通過操作對象的代理對象來間接來操作對象,達到預(yù)期的目的~
什么?還沒表述清楚?下面我們看個例子,就一目了然了~
let obj = { a : 1 } let proxyObj = new Proxy(obj,{ get : function (target,prop) { return prop in target ? target[prop] : 0 }, set : function (target,prop,value) { target[prop] = 888; } }) console.log(proxyObj.a); // 1 console.log(proxyObj.b); // 0 proxyObj.a = 666; console.log(proxyObj.a) // 888
上述例子中,我們事先定義了一個對象 obj , 通過 Proxy 構(gòu)造器生成了一個 proxyObj 對象,并對其的 set(寫入) 和 get (讀取) 行為重新做了修改。
當我們訪問對象內(nèi)原本存在的屬性時,會返回原有屬性內(nèi)對應(yīng)的值,如果試圖訪問一個不存在的屬性時,會返回0 ,即我們訪問 proxyObj.a 時,原本對象中有 a 屬性,因此會返回 1 ,當我們試圖訪問對象中不存在的 b 屬性時,不會再返回 undefined ,而是返回了 0 ,當我們試圖去設(shè)置新的屬性值的時候,總是會返回 888 ,因此,即便我們對 proxyObj.a 賦值為 666 ,但是并不會生效,依舊會返回 888!
語法
ES6 原生提供的 Proxy 語法很簡單,用法如下:
let proxy = new Proxy(target, handler);
參數(shù) target 是用 Proxy 包裝的目標對象(可以是任何類型的對象,包括原生數(shù)組,函數(shù),甚至另一個代理), 參數(shù) handler 也是一個對象,其屬性是當執(zhí)行一個操作時定義代理的行為的函數(shù),也就是自定義的行為。
Proxy 的基本用法就如同上面這樣,不同的是 handler 對象的不同,handler 可以是空對象 {} ,則表示對 proxy 操作就是對目標對象 target 操作,即:
let obj = {} let proxyObj = new Proxy(obj,{}) proxyObj.a = 1; proxyObj.fn = function () { console.log('it is a function') } console.log(proxyObj.a); // 1 console.log(obj.a); // 1 console.log(obj.fn()) // it is a function
但是要注意的是,handler 不能 設(shè)置為 null ,會拋出一個錯誤——Cannot create proxy with a non-object as target or handler!
要想 Proxy 起作用,我們就不能去操作原來對象的對象,也就是目標對象 target (上例是 obj 對象 ),必須針對的是 Proxy 實例(上例是 proxyObj 對象)進行操作,否則達不到預(yù)期的效果,以剛開始的例子來看,我們設(shè)置 get 方法后,視圖繼續(xù)從原對象 obj 中讀取一個不存在的屬性 b , 結(jié)果依舊返回 undefined :
console.log(proxyObj.b); // 1 console.log(obj.b); // undefined
對于可以設(shè)置、但沒有設(shè)置攔截的操作,則對 proxy 對象的處理結(jié)果也同樣會作用于原來的目標對象 target 上,怎么理解呢?還是以剛開始的例子來看,我們重新定義了 set 方法,所有的屬性設(shè)置都返回了 888 , 并沒有對某個特殊的屬性(這里指的是 obj 的 a 屬性 )做特殊的攔截或處理,那么通過 proxyObj.a = 666 操作后的結(jié)果同樣也會作用于原來目標對象(obj 對象)上,因此 obj 對象的 a 的值也將會變?yōu)?888 !
proxyObj.a = 666; console.log( proxyObj.a); // 888 console.log( obj.a); // 888
API
ES6 中 Proxy 目前提供了 13 種可代理操作,下面我對幾個比較常用的 api 做一些歸納和整理,想要了解其他方法的同學可自行去官網(wǎng)查閱 :
--handler.get(target,property,receiver)
用于攔截對象的讀取屬性操作,target 是指目標對象,property 是被獲取的屬性名 , receiver 是 Proxy 或者繼承 Proxy 的對象,一般情況下就是 Proxy 實例。
let proxy = new Proxy({},{ get : function (target,prop) { console.log(`get ${prop}`); return 10; } }) console.log(proxy.a) // get a // 10
我們攔截了一個空對象的 讀取get操作, 當獲取其內(nèi)部的屬性是,會輸出 get ${prop} , 并返回 10 ;
let proxy = new Proxy({},{ get : function (target,prop,receiver) { return receiver; } }) console.log(proxy.a) // Proxy{} console.log(proxy.a === proxy) //true
上述 proxy 對象的 a 屬性是由 proxy 對象提供的,所以 receiver 指向 proxy 對象,因此 proxy.a === proxy 返回的是 true。
要注意,如果要訪問的目標屬性是不可寫以及不可配置的,則返回的值必須與該目標屬性的值相同,也就是不能對其進行修改,否則會拋出異常~
let obj = {}; Object.defineProperty(obj, "a", { configurable: false, enumerable: false, value: 10, writable: false }); let proxy = new Proxy(obj,{ get : function (target,prop) { return 20; } }) console.log(proxy.a) // Uncaught TypeError
上述 obj 對象中的 a 屬性不可寫,不可配置,我們通過 Proxy 創(chuàng)建了一個 proxy 的實例,并攔截了它的 get 操作,當我們輸出 proxy.a 時會拋出異常,此時,如果我們將 get 方法的返回值修改跟目標屬性的值相同時,也就是 10 , 就可以消除異常~
--handler.set(target, property, value, receiver)
用于攔截設(shè)置屬性值的操作,參數(shù)于 get 方法相比,多了一個 value ,即要設(shè)置的屬性值~
在嚴格模式下,set方法需要返回一個布爾值,返回 true 代表此次設(shè)置屬性成功了,如果返回false且設(shè)置屬性操作失敗,并且會拋出一個TypeError。
let proxy = new Proxy({},{ set : function (target,prop,value) { if( prop === 'count' ){ if( typeof value === 'number'){ console.log('success') target[prop] = value; }else{ throw new Error('The variable is not an integer') } } } }) proxy.count = '10'; // The variable is not an integer proxy.count = 10; // success
上述我們通過修改 set方法,對 目標對象中的 count 屬性賦值做了限制,我們要求 count 屬性賦值必須是一個 number 類型的數(shù)據(jù),如果不是,就返回一個錯誤 The variable is not an integer,我們第一次為 count 賦值字符串 '10' , 拋出異常,第二次賦值為數(shù)字 10 , 打印成功,因此,我們可以用 set 方法來做一些數(shù)據(jù)校驗!
同樣,如果目標屬性是不可寫及不可配置的,則不能改變它的值,即賦值無效,如下:
let obj = {}; Object.defineProperty(obj, "count", { configurable: false, enumerable: false, value: 10, writable: false }); let proxy = new Proxy(obj,{ set : function (target,prop,value) { target[prop] = 20; } }) proxy.count = 20 ; console.log(proxy.count) // 10
上述 obj 對象中的 count 屬性,我們設(shè)置它不可被修改,并且默認值,我們給定為 10 ,那么即使給其賦值為 20 ,結(jié)果仍舊沒有變化!
--handler.apply(target, thisArg, argumentsList)
用于攔截函數(shù)的調(diào)用,共有三個參數(shù),分別是目標對象(函數(shù))target,被調(diào)用時的上下文對象 thisArg 以及被調(diào)用時的參數(shù)數(shù)組 argumentsList,該方法可以返回任何值。
target 必須是是一個函數(shù)對象,否則將拋出一個TypeError;
function sum(a, b) { return a + b; } const handler = { apply: function(target, thisArg, argumentsList) { console.log(`Calculate sum: ${argumentsList}`); return target(argumentsList[0], argumentsList[1]) * 10; } }; let proxy = new Proxy(sum, handler); console.log(sum(1, 2)); // 3 console.log(proxy(1, 2)); // Calculate sum:1,2 // 6
實際上,apply 還會攔截目標對象的 Function.prototype.apply() 和 Function.prototype.call(),以及 Reflect.apply() 操作,如下:
console.log(proxy.call(null, 3, 4)); // Calculate sum:3,4 // 14 console.log(Reflect.apply(proxy, null, [5, 6])); // Calculate sum: 5,6 // 22
--handler.construct(target, argumentsList, newTarget)
construct 用于攔截 new 操作符,為了使 new 操作符在生成的 Proxy對象上生效,用于初始化代理的目標對象自身必須具有[[Construct]]內(nèi)部方法;它接收三個參數(shù),目標對象 target ,構(gòu)造函數(shù)參數(shù)列表 argumentsList 以及最初實例對象時,new 命令作用的構(gòu)造函數(shù),即下面例子中的 p。
let p = new Proxy(function() {}, { construct: function(target, argumentsList, newTarget) { console.log(newTarget === p ); // true console.log('called: ' + argumentsList.join(', ')); // called:1,2 return { value: ( argumentsList[0] + argumentsList[1] )* 10 }; } }); console.log(new p(1,2).value); // 30
另外,該方法必須返回一個對象,否則會拋出異常!
var p = new Proxy(function() {}, { construct: function(target, argumentsList, newTarget) { return 2 } }); console.log(new p(1,2)); // Uncaught TypeError
--handler.has(target,prop)
has方法可以看作是針對 in 操作的鉤子,當我們判斷對象是否具有某個屬性時,這個方法會生效,典型的操作就是 in ,改方法接收兩個參數(shù) 目標對象 target 和 要檢查的屬性 prop,并返回一個 boolean 值。
let p = new Proxy({}, { has: function(target, prop) { if( prop[0] === '_' ) { console.log('it is a private property') return false; } return true; } }); console.log('a' in p); // true console.log('_a' in p ) // it is a private property // false
上述例子中,我們用 has 方法隱藏了屬性以下劃線_開頭的私有屬性,這樣在判斷時候就會返回 false,從而不會被 in 運算符發(fā)現(xiàn)~
要注意,如果目標對象的某一屬性本身不可被配置,則該屬性不能夠被代理隱藏,如果目標對象為不可擴展對象,則該對象的屬性不能夠被代理隱藏,否則將會拋出 TypeError。
let obj = { a : 1 }; Object.preventExtensions(obj); // 讓一個對象變的不可擴展,也就是永遠不能再添加新的屬性 let p = new Proxy(obj, { has: function(target, prop) { return false; } }); console.log('a' in p); // TypeError is thrown
數(shù)據(jù)綁定
上面介紹了這么多,也算是對 Proxy 又來一個初步的了解,那么我們就可以利用 Proxy 手動實現(xiàn)一個極其簡單數(shù)據(jù)的雙向綁定(Object.defineProperty() 的實現(xiàn)方式可以參考我上篇文章的末尾有涉及到)~
主要看功能的實現(xiàn),所以布局方面我就隨手一揮了~
頁面結(jié)構(gòu)如下:
<!--html--> <div id="app"> <h4 id="paragraph"></h4> <input type="text" id="input"/> </div>
主要還是得看邏輯部分:
//獲取段落的節(jié)點 const paragraph = document.getElementById('paragraph'); //獲取輸入框節(jié)點 const input = document.getElementById('input'); //需要代理的數(shù)據(jù)對象 const data = { text: 'hello world' } const handler = { //監(jiān)控 data 中的 text 屬性變化 set: function (target, prop, value) { if ( prop === 'text' ) { //更新值 target[prop] = value; //更新視圖 paragraph.innerHTML = value; input.value = value; return true; } else { return false; } } } //添加input監(jiān)聽事件 input.addEventListener('input', function (e) { myText.text = e.target.value; //更新 myText 的值 }, false) //構(gòu)造 proxy 對象 const myText = new Proxy(data,handler); //初始化值 myText.text = data.text;
以上是“Vue3.0中Proxy怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)站標題:Vue3.0中Proxy怎么用-創(chuàng)新互聯(lián)
分享鏈接:http://jinyejixie.com/article40/dcjceo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、品牌網(wǎng)站設(shè)計、軟件開發(fā)、App開發(fā)、微信小程序、自適應(yīng)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容