日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

从Proxy到Vue3数据绑定

發布時間:2025/4/16 vue 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从Proxy到Vue3数据绑定 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

導言: 本菜雞在Vue2沒多久,結果就Vue3發布了。趕緊學習和體驗了一番Vue3,發現和Vue2有較大不同。其中最讓我印象深刻的是他們有一個叫ref和reactive的用來綁定和更新數據。然后再略微調查原理之后發現Vue3是用的Proxy來實現數據綁定。我之前對JS語法的Proxy基本完全不懂,正好趁這個機會,深入理解一下Proxy和Vue3的數據綁定。希望對于同樣是初學者的你,看完我的文章,能對這兩部分知識有更深入的認識。

數據綁定

我們進行網頁設計,除了需要設計各個頁面組件之外,另外最重要的部分應該就屬于數據交互了。經常我們要面對的需求是獲取用戶的數據或者將一些處理過的數據發送給用戶。比如我們用原生代碼展示一下上將數據發送給用戶:

<p></p> const data = { value: 'hello' } document.querySelector('p').innerText = data.value;

等到我們使用Vue之后,Vue引入了一種設計模式稱為MVVM,我們不再和DOM直接進行交互。

MVVM是Model-View-ViewModel縮寫,也就是把MVC中的Controller演變成ViewModel。Model層代表數據模型,View代表UI組件,ViewModel是View和Model層的橋梁,數據會綁定到viewModel層并自動將數據渲染到頁面中,視圖變化的時候會通知viewModel層更新數據。


上圖是一個經驗的MVVM的示意圖,我們在使用Vue的時候,只設計UI以及數據處理的Model。如何將數據渲染在頁面上,我們不再關心了。交給Vue來處理。

可以再看一下,我們最開始舉得簡單代碼的例子。之前我們是View和Model直接進行通信的,現在多了一個ViewModel層。就像假設你之前出入小區可以隨便出入。現在因為疫情,門口多了一個站崗的保安。你能不能出入不再是由你決定了,而是由保安決定。這樣的保安或者ViewModel,可以稱之為一種代理。

類似于交易不是雙方直接達成,而是要經過中間商才能達成交易。類似于你們之前是直接現金交易,現在都需要用支付寶轉到對方賬戶才行。支付寶就是這樣的中間商或者稱為代理。有了代理就可以設置一些處理規則,或者攔截等。比如支付寶可以定義一種代理規則:只要是通過我轉賬到對方賬戶,我就要收取1%的手續費。

Proxy

我們理解了代理這個概念之間,下面就可以開始講Proxy。首先看一下MDN關于Proxy的定義:

Proxy 對象用于創建一個對象的代理,從而實現基本操作的攔截和自定義(如屬性查找、賦值、枚舉、函數調用等)

總之,Proxy就是干代理的事。就是前文講的那個保安或者支付寶。

關于Proxy最簡單的講解,我就不去貼MDN的內容了,如果對Proxy具體語法完全不了解請移步Proxy,Proxy的handler對象方法雖然很多,但最最常用的還是get和set。如果完全不了解Proxy的,別的對象方法可以暫時不看,一定要把這兩個方法看一下。

下面我舉一些Proxy的通俗例子,并逐漸過渡到Vue3的Proxy中。

首先舉一個簡單的例子:

let o = {name: 'xiaoming',age: 20 }let handler = {get(obj, key) {return key in obj ? obj[key] : ''} }let p = new Proxy(o, handler)console.log(p.from)

這個代碼是想表達如果 o 對象有這個 key-value 則直接返回,如果沒有一律返回空。這里的p的結果就相當于是一個代理過后的結果了,o的數據不是直接傳給p,而是經過經過handler代理邏輯之后才傳過去的。對于對象o而言,如果直接訪問o.from會報錯。對于p而言,因為中間有一個代理程序幫我們處理了一下,所以不會報錯,而是返回空。

通過上面的例子,我們初步了解了Proxy的代理特性,下面我們來看一下更復雜一點的例子。

let user = {name: 'xiaoming',age: 20,_password: '***' } user = new Proxy(user, {get(target, prop) {if (prop.startsWith('_')) {throw new Error('不可訪問')} else {return target[prop]}},set(target, prop, val) {if (prop.startsWith('_')) {throw new Error('不可訪問')} else {target[prop] = valreturn true}},deleteProperty(target, prop) { // 攔截刪除if (prop.startsWith('_')) {throw new Error('不可刪除')} else {delete target[prop]return true}},ownKeys(target) {return Object.keys(target).filter(key => !key.startsWith('_'))} }) console.log(user.age) console.log(user._password) user.age = 18 console.log(user.age) try {user._password = 'xxx' } catch (e) {console.log(e.message) }try {// delete user.agedelete user._password } catch (e) {console.log(e.message) } console.log(user.age)for (let key in user) {console.log(key) }

大家可以執行一下代碼看看輸出效果。關于Proxy的基本介紹就先到這里,下面我們來看看Vue3中是如何使用Proxy實現數據綁定的。

Vue3中的Proxy

在Vue3中我們使用ref和reactive來實現數據綁定。更改ref或者reactive實例化對象的值,會導致頁面中的數據也發生對應更改。之所以能夠實現更改ref或者reactive對應的值使得頁面的值發生對應變化是因為我們實際操作的數據是經過Proxy代理過后的,而在Proxy代理中,我們有具體定義頁面數據刷新的代碼。我用代碼舉一個很簡單的例子:

let obj = {name: 'xiaoming', age: 20} let state = new Proxy(obj, {get (obj, key) {return obj[key]},set (obj, key, value) {obj[key] = valueconsole.log('更新UI界面')// set方法必須通過返回值告訴Proxy此次操作是否成功return true} })console.log(state.name) state.age = 22

你可以執行一下上述代碼看看執行效果。當我們去設置一個值的時候,就會具體執行更能UI界面的操作。通過Proxy就可以實現ref和reactive的頁面更新和數據綁定,這也是ref和reactive背后的基本原理。

我們下面來談談reactive和ref的Proxy具體實現。

我們在使用Vue3的時候,通常使用ref來監聽一些簡單數據類型如數字、字符串、布爾等。你可能注意到一種現象,是更改ref的值的時候,需要使用ref.value的形式,(在template中使用ref時,Vue自動幫我們添加.value了,所以不需要我們手動添加),看起來很神奇,為什么會有一個.value呢?是因為ref本質上是一個包裝過后的reactive。在你去定義ref的時候,Vue會內部幫我們包裝一下。

let age = ref(18) // 等價于 let age = reactive({value: 18})

對于reactive,使用Proxy來完成對象監聽要更復雜一些,因為對象里面可能還嵌套對象,比如下面這種形式的對象:

let arr = [{id:1, name: '魯班'}, {id:2, name: '虞姬'}] let obj = {a:{id:1, name: '魯班'}, b:{id:2, name: '虞姬'}}

所以我們需要對每一層的對象都監聽到,才能做到當數據發生變化時,實現對應的更新。要實現一層一層的監聽,往往就會想到使用遞歸來實現。下面是代碼演示:

function reactive(obj) {if (typeof obj === 'object') {if (obj instanceof Array) {// 如果是一個數組,則取出數組中每一個元素,// 判斷每一個元素是否是一個對象,如果又是一個對象,則也需要包裝成Proxyobj.forEach((item, index) => {if (typeof item === 'object') {obj[index] = reactive(item)}})} else {// 如果是一個對象,則取出對象中的每一個屬性,// 判斷屬性是否又是一個對象,如果又是一個對象,則也需要包裝成Proxyfor (let key in obj) {let item = obj[key]if (typeof item === 'object') {obj[key] = reactive(item)}}}return new Proxy(obj, {get (obj, key) {return obj[key]},set (obj, key, val) {obj[key] = valconsole.log('更新UI界面')return true}})} else {console.warn(`${obj} is not object`)} }

你可以執行一些測試看看效果,看看會輸出什么。

let state = reactive(arr) state[0].name = 'zhangsan' state[1].id = 3

對于ref而言,因為ref是包裝過的reactive,所以使用reactive就可以定義ref:

function ref(val) {return reactive({value: val}) }
參考資料

[1] Vue雙向數據綁定
[2] Vue面試題總結
[3] Proxy
[4] Vue3 的 Proxy 和 defineProperty 的比較
[5] Vue3.0教程

總結

以上是生活随笔為你收集整理的从Proxy到Vue3数据绑定的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 福利综合网| 扒开伸进免费视频 | 国产精品一区免费观看 | 男人插女人免费视频 | 亚洲色图15p| 国产黑丝91 | 91视频精品 | 俺来也俺也啪www色 欧洲一区二区视频 | 国产在线精品成人欧美 | 亚洲国产精品视频在线观看 | 午夜精品久久久久久久久久蜜桃 | 玖玖热在线视频 | 狠狠干中文字幕 | 天天操夜夜欢 | 成年人在线播放视频 | 免费在线看黄网站 | 我们的生活第五季在线观看免费 | 国产视频精品在线 | youjizz.com中国 | 国产精品天天操 | 香蕉视频色 | 蜜桃视频在线网站 | 30一40一50老女人毛片 | 97xxx| 国产盗摄在线观看 | 黄色小视频免费看 | 久久久蜜桃一区二区 | 中文字幕一二三四 | 亚洲乱淫| 青青草娱乐视频 | 欧美日本一区 | 国产久精品 | 亚洲免费黄网 | 女人18毛片毛片毛片毛片区二 | 国产精品免费看片 | 白浆av| 91久久影院 | 天堂中文网 | 欧美精品videos极品 | 国产极品久久久 | 翔田千里一区二区三区av | 午夜精品久久久久久久 | 成年人在线观看 | 成年人免费网站在线观看 | 在线观看亚洲天堂 | 国产又粗又猛又爽又黄视频 | 国产良妇出轨视频在线观看 | 午夜精产品一区二区在线观看的 | 国产三级国产精品国产专区50 | 天天操天天摸天天干 | 五月花婷婷 | 韩国毛片视频 | 欧美色射 | 亚洲一区二区三区91 | 国模少妇一区二区三区 | 欧美黑人疯狂性受xxxxx喷水 | 中文字幕无码av波多野吉衣 | 性喷潮久久久久久久久 | 一道本久在线中文字幕 | 亚洲成人精品一区二区三区 | 狠狠爱综合| 在线观看欧美一区二区三区 | 毛片大全在线观看 | 国产精品又黄又爽又色无遮挡 | av永久免费网站 | 天天曰天天干 | 另类专区亚洲 | 久草成人网| 成人a站 | 91在线高清视频 | 国产精品久久一区二区三区 | 久久福利社 | 美女黄色影院 | 精品xxxxx| 蜜臀久久99精品久久久无需会员 | 精品中文字幕视频 | 中文字幕av专区dvd | 篠田优在线观看 | 日日夜夜影院 | 啪视频网站 | 欧美一道本| 欧美精选一区 | 亚洲精品.www | 六月丁香色婷婷 | 国产精品色婷婷99久久精品 | 99国产成人精品 | 无码一区二区精品 | 精品国产青草久久久久96 | 全黄一级片 | 成人网免费 | 最新中文字幕在线观看 | 欧美日韩亚洲国产精品 | 乱日视频| 欧美激情性做爰免费视频 | 456亚洲影院 | 三级a毛片 | 久久在草 | 国产传媒视频在线 | 在线观看国产区 |