作者:楠楠妈妈05乄23 | 来源:互联网 | 2020-09-12 10:15
随着vue3.x的消息越来越多,proxy的讨论也。相对于Object.defineProperty,proxy有什么区别,有什么优势,以及可以应用在什么地方,该文章就简单的介绍下。
开汽车的人往往不了解汽车的构造,但是深入了解汽车的构造,可能会有如虎添翼的效果
前言
随着 vue3.x
的消息越来越多,proxy
的讨论也。相对于 Object.defineProperty
,proxy
有什么区别,有什么优势,以及可以应用在什么地方。该文章就简单的介绍下
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
执行一下,似乎能正常运行
由上图得知,虽然数组属性实际上是修改成功了,但是不能被监听到
问题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)
也是一样的效果
表单校验
在对表单的值进行改动的时候,可以在 set
里面进行拦截,判断值是否合法
let ecValidate = {
set(target, key, value, receiver) {
if (key === 'age') { //如果值小于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;
增加附加属性
比如有一个需求,保证用户输入正确身份证号码之后,把出生年月,籍贯,性别都添加进用户信息里面
众所周知,身份证号码第一和第二位代表所在省(自治区,直辖市,特别行政区),第三和第四位代表所在市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。第七至第十四位是出生年月日。低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)
数据格式化
比如有一个需求,需要传时间戳给到后端,但是前端拿到的是一个时间字符串,这个也可以用 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教程》
以上就是JS Proxy 的优势以及使用场景的详细内容,更多请关注 第一PHP社区 其它相关文章!