目錄
前言" >前言
Object.defineProperty" >Object.defineProperty
gender,能夠監聽到" > 做不到的事情,例如增加一個屬性gender,能夠監聽到
表单校验" >表单校验
增加附加属性" >增加附加属性
数据格式化" >数据格式化
首頁 web前端 js教程 JS Proxy 的優勢以及使用場景

JS Proxy 的優勢以及使用場景

Jun 15, 2020 am 09:22 AM
javascript js vue

JS Proxy 的優勢以及使用場景

開車的人往往不了解汽車的構造,但是深入了解汽車的構造,可能會有如虎添翼的效果

前言

隨著vue3.x 的訊息越來越多,proxy 的討論也。相對於 Object.definePropertyproxy 有什麼區別,有什麼優勢,以及可以應用在什麼地方。文章就簡單的介紹下

Object.defineProperty

proxy 之前,先回顧一下Object.defineProperty# 。大家都知道,vue2.x 以及之前的版本是使用 Object.defineProperty 實作資料的雙向綁定的,至於是怎樣綁定的呢?下面簡單實作一下

function observer(obj) {
    if (typeof obj === 'object') {
        for (let key in obj) {
            defineReactive(obj, key, obj[key])
        }
    }
}
function defineReactive(obj, key, value) { //针对value是对象,递归检测
    observer(value) //劫持对象的key
    Object.defineProperty(obj, key, {
        get() {
            console.log('获取:' + key) return value
        },
        set(val) { //针对所设置的val是对象
            observer(val) console.log(key + "-数据改变了") value = val
        }
    })
}
let obj = {
    name: '守候',
    flag: {
        book: {
            name: 'js',
            page: 325
        },
        interest: ['火锅', '旅游'],
    }
}

observer(obj)
登入後複製

在瀏覽器的console 執行一下,似乎能正常運行

JS Proxy 的優勢以及使用場景

但是實際上,Object.defineProperty 問題有以下幾個

問題1.刪除或增加物件屬性無法監聽到

例如增加一個屬性gender ,由於在執行observer(obj) 的時候,沒有這個屬性,所以這個無法監聽到。刪除的屬性也是無法監聽到

增加屬性的時候,vue 需要使用$set 來操作,$set 的內部也是使用Object.defineProperty 來操作

JS Proxy 的優勢以及使用場景

#問題2.陣列的變化無法監聽到

JS Proxy 的優勢以及使用場景

JS Proxy 的優勢以及使用場景

JS Proxy 的優勢以及使用場景

JS Proxy 的優勢以及使用場景

#由上圖得知,雖然陣列屬性其實是修改成功了,但是不能被監聽到

#問題3. 由於是使用遞歸遍歷對象,使用

Object.defineProperty  劫持物件的屬性,如果遍歷的物件層級比較深,花的時間比較久,甚至有效能的問題# proxy

對於proxy ,在mdn 上的描述是: 物件用於定義基本操作的自訂行為(如屬性查找、賦值、枚舉、函數呼叫等)

簡單來說就是,可以在對目標物件設定一層攔截。無論對目標物件進行什麼操作,都要經過這層攔截

聽上去似乎,proxy

Object.defineProperty 要好用,並且簡單很多,實際上就是如此。下面用proxy 對上面的程式碼進行改寫試下

function observerProxy(obj) {
    let handler = {
        get(target, key, receiver) {
            console.log('获取:' + key) // 如果是对象,就递归添加 proxy 拦截
            if (typeof target[key] === 'object' && target[key] !== null) {
                return new Proxy(target[key], handler)
            }
            return Reflect.get(target, key, receiver)
        },
        set(target, key, value, receiver) {
            console.log(key + "-数据改变了") return Reflect.set(target, key, value, receiver)
        }
    }
    return new Proxy(obj, handler)
}
let obj = {
    name: '守候',
    flag: {
        book: {
            name: 'js',
            page: 325
        },
        interest: ['火锅', '旅游'],
    }
}
let objTest = observerProxy(obj)
登入後複製
也是一樣的效果

而且,能做到

Object.defineProperty

做不到的事情,例如增加一個屬性gender,能夠監聽到

#操作數組,也能監聽到#最後敲一下黑板,簡單總結一下兩者的差異

1.JS Proxy 的優勢以及使用場景Object.defineProperty

攔截的是物件的屬性,會改變原始物件。 ###proxy### 是攔截整個對象,透過 new 產生一個新對象,不會改變原始對象。 ######2.###proxy### 的攔截方式,除了上面的 get 和 set ,還有 11 種。選擇的方式很多 Proxy,也可以監聽一些  ###Object.defineProperty### 監聽不到的操作,例如監聽數組,監聽物件屬性的新增,刪除等。 #########proxy 使用場景#########關於###proxy### 的使用場景,受限於篇幅,這裡就簡單列舉幾個,更多的可以移步我的github 筆記或mdn。 ######看到這裡,兩者的差別,和 ###proxy### 的優勢已經知道個大概了。但是在開發上,有哪些場景可以使用到###proxy### 呢,下面列舉個可能會遇到的情況#########負索引數組#########在使用###splice(-1)###,###slice(-1)### 等API 的時候,當輸入負數的時候,會定位到陣列的最後一項,但在普通陣列上,並不能使用負數。 ###[1,2,3][-1]### 這個程式碼並不能輸出 3 。要讓上面的程式碼輸出 3 , 也可以使用 ###proxy### 實作。 ###
<br>
登入後複製
##########

表单校验

在对表单的值进行改动的时候,可以在 set 里面进行拦截,判断值是否合法

let ecValidate = {
    set(target, key, value, receiver) {
        if (key === &#39;age&#39;) { //如果值小于0,或者不是正整数
            if (value < 0 || !Number.isInteger(value)) {
                throw new TypeError(&#39;请输入正确的年龄&#39;);
            }
        }
        return Reflect.set(target, key, value, receiver)
    }
}
let obj = new Proxy({
    age: 18
},
ecValidate) obj.age = 16obj.age = &#39;少年&#39;
登入後複製

JS Proxy 的優勢以及使用場景

增加附加属性

比如有一个需求,保证用户输入正确身份证号码之后,把出生年月,籍贯,性别都添加进用户信息里面

众所周知,身份证号码第一和第二位代表所在省(自治区,直辖市,特别行政区),第三和第四位代表所在市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。第七至第十四位是出生年月日。低17位代表性别,男单女双。

const PROVINCE_NUMBER = {
    44 : &#39;广东省&#39;,
    46 : &#39;海南省&#39;
}
const CITY_NUMBER = {
    4401 : &#39;广州市&#39;,
    4601 : &#39;海口市&#39;
}
let ecCardNumber = {
    set(target, key, value, receiver) {
        if (key === &#39;cardNumber&#39;) {
            Reflect.set(target, &#39;hometown&#39;, PROVINCE_NUMBER[value.substr(0, 2)] + CITY_NUMBER[value.substr(0, 4)], receiver) Reflect.set(target, &#39;date&#39;, value.substr(6, 8), receiver) Reflect.set(target, &#39;gender&#39;, value.substr( - 2, 1) % 2 === 1 ? &#39;男&#39;: &#39;女&#39;, receiver)
        }
        return Reflect.set(target, key, value, receiver)
    }
}
let obj = new Proxy({
    cardNumber: &#39;&#39;
},
ecCardNumber)
登入後複製

JS Proxy 的優勢以及使用場景

数据格式化

比如有一个需求,需要传时间戳给到后端,但是前端拿到的是一个时间字符串,这个也可以用 proxy 进行拦截,当得到时间字符串之后,可以自动加上时间戳。

let ecArrayProxy = {
    get(target, key, receiver) {
        let _index = key < 0 ? target.length + Number(key) : key
        return Reflect.get(target, _index, receiver)
    }
}
let arr = new Proxy([1, 2, 3], ecArrayProxy)
登入後複製

JS Proxy 的優勢以及使用場景<br>

推荐教程:《JS教程》    <br>

以上是JS Proxy 的優勢以及使用場景的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

vue中怎麼用bootstrap vue中怎麼用bootstrap Apr 07, 2025 pm 11:33 PM

在 Vue.js 中使用 Bootstrap 分為五個步驟:安裝 Bootstrap。在 main.js 中導入 Bootstrap。直接在模板中使用 Bootstrap 組件。可選:自定義樣式。可選:使用插件。

vue怎麼給按鈕添加函數 vue怎麼給按鈕添加函數 Apr 08, 2025 am 08:51 AM

可以通過以下步驟為 Vue 按鈕添加函數:將 HTML 模板中的按鈕綁定到一個方法。在 Vue 實例中定義該方法並編寫函數邏輯。

vue中的watch怎麼用 vue中的watch怎麼用 Apr 07, 2025 pm 11:36 PM

Vue.js 中的 watch 選項允許開發者監聽特定數據的變化。當數據發生變化時,watch 會觸發一個回調函數,用於執行更新視圖或其他任務。其配置選項包括 immediate,用於指定是否立即執行回調,以及 deep,用於指定是否遞歸監聽對像或數組的更改。

vue多頁面開發是啥意思 vue多頁面開發是啥意思 Apr 07, 2025 pm 11:57 PM

Vue 多頁面開發是一種使用 Vue.js 框架構建應用程序的方法,其中應用程序被劃分為獨立的頁面:代碼維護性:將應用程序拆分為多個頁面可以使代碼更易於管理和維護。模塊化:每個頁面都可以作為獨立的模塊,便於重用和替換。路由簡單:頁面之間的導航可以通過簡單的路由配置來管理。 SEO 優化:每個頁面都有自己的 URL,這有助於搜索引擎優化。

vue.js怎麼引用js文件 vue.js怎麼引用js文件 Apr 07, 2025 pm 11:27 PM

在 Vue.js 中引用 JS 文件的方法有三種:直接使用 &lt;script&gt; 標籤指定路徑;利用 mounted() 生命週期鉤子動態導入;通過 Vuex 狀態管理庫進行導入。

vue返回上一頁的方法 vue返回上一頁的方法 Apr 07, 2025 pm 11:30 PM

Vue.js 返回上一頁有四種方法:$router.go(-1)$router.back()使用 &lt;router-link to=&quot;/&quot;&gt; 組件window.history.back(),方法選擇取決於場景。

vue遍歷怎麼用 vue遍歷怎麼用 Apr 07, 2025 pm 11:48 PM

Vue.js 遍歷數組和對像有三種常見方法:v-for 指令用於遍歷每個元素並渲染模板;v-bind 指令可與 v-for 一起使用,為每個元素動態設置屬性值;.map 方法可將數組元素轉換為新數組。

vue的div怎麼跳轉 vue的div怎麼跳轉 Apr 08, 2025 am 09:18 AM

Vue 中 div 元素跳轉的方法有兩種:使用 Vue Router,添加 router-link 組件。添加 @click 事件監聽器,調用 this.$router.push() 方法跳轉。

See all articles