赞
踩
function reactive( obj ) {
return new Proxy ( obj, {
get(target,key){},
set(target,key,val) {},
deleteProperty(target,key){}
}
}
001: 在vue2之中,假如设置了obj:{a:1} 若是给obj对象添加一个b属性值,直接在methods之中使用方法 obj.b = 2,导致的问题是:数据有更新,但是视图没有更新( 需要使用this.$set()方法去设置b属性为响应式属性值,才能支持试图更新 );vue3之中直接使用reactive定义对象,则当前对象为响应式对象,对于obj.b = 2 视图会更新!
002: object.defineProperty对于后期添加的属性值是不参与劫持设置为响应式属性的,这就是为什么上面obj.b没有更新视图的缘故
002: new Proxy对于后期添加的属性值是依旧走proxy内的set和get,这就是obj.b更新视图的缘故
// vue2 设置响应式属性demo
let obj = {
a: 1,
b: 2
}
let vue = {}
for (let k in obj) {
Object.defineProperty(vue, k, {
get() {
console.log('获取了')
return obj[k]
},
set(value) {
obj[k] = value
}
})
}
console.log('obj', obj) // obj {a: 1, b: 2}
vue.c = '000'
console.log('vue-c', vue.c) // vue-c 000 没有走 Object.defineProperty这个逻辑
console.log('vue-a', vue.a) // 获取了 vue-a 1 打印了,由于有a属性,则走了Object.defineProperty这个逻辑
// vue3 设置响应式属性demo
let obj = {
a: 1,
b: 2
}
let vue = {}
vue = new Proxy(obj, {
get(target, key, receiver) {
console.log('获取了')
return Reflect.get(target, key, receiver)
},
set(target, key, val, receiver) {
console.log('设置了')
return Reflect.set(target, key, val, receiver)
},
deleteProperty(target, key) {}
})
vue.c = '000'
console.log('vue-c', vue.c) // vue-c 000 设置了 获取了 vue3之中走了new Proxy的逻辑,设置为了响应式数据
1:Composition API 组合api
2:Teleport 传送组件,把dom节点挂载到body等其他标签上
3:Fragments 碎片化节点 ( 不需要根节点 )
4:Emits Component Option自定义事件
5:createRenderer 渲染器
6:SFC State-driven CSS Variables (v-bind in style)
7:SFC style scoped can now include global rules or rules that target only slotted content
8:Suspense组件 异步组件
再说说框架特性:
vue3对于vue2来说,最大的变化就是composition Api 替换了vue2的options Api
vue3的响应式原理替换为了proxy,vue2的则是Object.defineproperty。其中proxy有着以下这些优点:
- 1:对象新增的属性不需要使用$set添加响应式,因为proxy默认会监听动态添加属性和删除属性等操作
- 2:消除数组上无法监听数组索引、length属性,不再进行数组原型对象上重写数组方法
- 3:Object.defineproperty是劫持所有对象的属性设置为getter、setter,然后遍历递归去实现。而proxy则是代理了整个对象。
- 4:vue2使用Object.defineproperty拦截对象的get和set属性进行操作。而proxy有着13种拦截方法。
- 5:由vue2的响应式原理可以看出,vue底层需要对vue实例的返回的每一个key进行get和set操作,无论这个值有没有被用到。所以在vue中定义的data属性越多,那么初始化开销就会越大。而proxy是一个惰性的操作,它只会在用到这个key的时候才会执行get,改值的时候才会执行set。所以在vue3中实现响应式的性能实际上要比vue2实现响应式性能要好
+ proxy原理
- 作用:能够为另外一个对象创建代理,该代理可以拦截和重新定义该对象的基本操作(获取,设置,定义属性等)
- proxy的两个参数: 参数1=> 要代理的原始对象; 参数2=>一个对象,这个对象定义了操作将被拦截以及如何重新定义被拦截的操作
``js
const target = {name: "ts",age: 18};
const handler = {};
const proxy = new Proxy(target, handler); // 使用proxy代理了一个空对象 proxy对象具有响应式
const target2 = {name: "ts",age: "18"};
const handler2 = {
get(target, key, receiver) {
console.log(`访问属性${key}值`)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.log(`设置属性${key}值`)
return Reflect.set(target, key, value, receiver)
}
};
const proxy2 = new Proxy(target2, handler2); // 使用proxy代理了一个handler2对象 handler2对象中设置了get和set属性
console.log('proxy2.name', proxy2.name)
proxy2.name = 'jkl';
proxy2.sex = 'male';
console.log('proxy2',proxy2);
``
1:Object.defineproperty 初始化的时候拦截对象,设置为get和set属性
const obj = {
name: "wxs",
age: 25,
};
Object.entries(obj).forEach(([key, value]) => {
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newValue) {
console.log(`监听到属性${key}改变`);
value = newValue;
},
});
});
obj.name = 11;
obj.age = 22;
obj.ak47 = "ak47";
1:输出结果 => 监听到属性name改变、监听到属性age改变
2: proxy 初始化的时候,有使用这个key值则get一下,有设置这个key值则set一下
const obj = {
name:'wxs',
age:25
}
const prxoyTarget = new Proxy(obj,{
get(target,key){
return target.key
},
set(target,key,value){
console.log(`监听到属性${key}需要改成${value}`)
target[key] = value
}
})
prxoyTarget.name = 11
prxoyTarget.age = 22
prxoyTarget.ak47 = 'ak47'
2:输出结果 => 监听到属性name需要改成11、监听到属性age需要改成22、监听到属性ak47需要改成ak47
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。