reactive源码解析
proxy是怎么代理的?
let handler = {
//拦截整个对象,访问对象的属性时get拦截器触发
get(target, key) {
let value = target[key];
if (typeof value === "object") {
//如果访问的对象属性还是对象,进行递归
return new Proxy(value, handler);
}
return value;
},
//拦截整个对象,当修改对象的属性的时候set拦截器会触发
set(target, key, value) {
target[key] = value;
},
};
function reactive(target) {
return new Proxy(target, handler);
}
let obj = { name: "jw", age: 30, n: [1, 2, 3, 4, 5] };
//拿到obj的代理对象proxyObj
const proxyObj = reactive(obj);
//不访问obj,访问代理对象proxyObj
console.log(proxyObj.name); //触发get拦截器
proxyObj.age = 31; //触发set拦截器
proxyObj.name = 100; //设置一个不存在的属性
get(target, property, receiver)
:拦截对象属性的读取操作,当访问代理对象的属性时会触发该方法。set(target, property, value, receiver)
:拦截对象属性的设置操作,当给代理对象的属性赋值时会触发该方法。
ref源码原理
为什么ref定义后的对象可以通过.value 访问和设置数据?
get 和 set 属性是一种在类中定义属性的方式,可以用来实现类的属性的读取和写入操作。基本语法如下:
class MyClass {
private _propertyName: any;
get propertyName(): any {
console.log("读取数据,自动进入get方法");
return this._propertyName;
}
set propertyName(value: any) {
this._propertyName = value;
console.log("更新数据,自动进入set方法");
}
}
在上面的例子中,propertyName
是一个类的属性,它使用 get 和 set 属性定义在 MyClass
类中。在类的外部,可以使用点操作符来读取和写入 propertyName
属性,例如:
const myObject = new MyClass();
myObject.propertyName = 'hello';//更新
console.log(myObject.propertyName); //访问
执行结果
当在类的外部读取 propertyName
属性时,会调用 propertyName
的 get 属性,返回 _propertyName
的值。当在类的外部写入 propertyName
属性时,会调用 propertyName
的 set 属性,将值赋给 _propertyName
属性。
为什么在类里这样写可以触发get和set呢?
var MyClass = /** @class */ (function () {
function MyClass() {
}
Object.defineProperty(MyClass.prototype, "propertyName", {
get: function () {
console.log("读取数据,自动进入get方法");
return this._propertyName;
},
set: function (value) {
this._propertyName = value;
console.log("更新数据,自动进入set方法");
},
enumerable: false,
configurable: true
});
return MyClass;
}());
var myObject = new MyClass();
myObject.propertyName = "hello";
console.log(myObject.propertyName);
vue3中ref实现
toReactive方法做了什么?
思考:为什么你更习惯使用ref而不是reactive?
-
简单性:
ref
提供了一种简单的方式来定义响应式对象,只需传入初始值即可。相比之下,reactive
需要将整个对象传入,稍显繁琐。对于单个变量或简单数据,使用ref
更加直观和方便。 -
透明性:
ref
返回的是一个包装过的对象,可以通过.value
访问其值,这种包装使得数据访问更加明确和直观。而reactive
返回的是原始对象,需要通过代理访问属性,有时会增加代码的复杂性。(复杂的代码谁想写啊) -
性能:在某些情况下,
ref
比reactive
更高效。因为ref
包装的是基本类型数据,而reactive
包装的是对象,对于简单数据类型,ref
的性能可能更好。 -
推荐度:Vue 3 官方文档和社区更倾向于推荐使用
ref
,因为它更简单、更直观,适用于大多数场景。而reactive
更适合处理复杂的对象或数据结构。