这是我参与11月更文挑战的第2天
reactive
reactive()函数的参数只能是Object
reactive通过ES6的new Proxy()给对象添加代理实现数据劫持
reactive 源码核心实现
function reactive( obj ){
return createReactiveObject(obj)
}
function createReactiveObject(obj){
const proxy = new Proxy(obj, {
get : function (obj, key, receiver= {}){
const res = Reflect.get(obj, key, receiver)
// 调用track(),收集依赖
return res
},
set : function(obj, key, value, receiver = {} ){
let oldValue = obj[key]
// 此时的receiver为this,即为proxy代理
const result = Reflect.set(obj, key, value, receiver)
if(oldValue !== value){
// 调用trigger() ,触发更新
}
return result
},
})
return proxy
}
let obj = {a : 1}
let objProxy = reactive(obj)
objProxy.a = 2
console.log(objProxy.a)
ref
ref()函数的参数可以是Object也可以是基本数据类型
如果是Object直接转给reactive()
如果是基本数据类型,通过ES6 Class的getter和setter实现数据劫持
ES6的Class的getter和setter本质就是通过Object.defineProperty与get、set方法实现
ref 源码核心实现
function ref(value){
return createRef(value)
}
function createRef(rawValue){
return new RefImpl(rawValue)
}
class RefImpl {
constructor(_rawValue){
// 类的this执行类的实例
this._value = _rawValue
}
get value(){
// 取值时,调用effect的track,收集依赖
track()
return this._value
}
set value(newVal){
// 赋值时,调用effect的trigger,触发更新
trigger()
this._value = newVal
}
}
let a = ref("123")
console.log(a.value)
a.value = "456"
console.log(a.value)
reactive 和 ref的区别
reactive 和 ref 都是用来定义响应式数据的。
reactive的参数只能是复杂的数据类型; ref的参数可以是基本能数据类型也可以是复杂的数据类型
reactive更推荐去定义复杂的数据类型; ref更推荐去定义基本类型。
reactive 是通过ES6的Proxy实现的数据劫持; ref是通过调用reactive实现复杂数据类型的数据劫持, 通过Object.defineProperty的get/set实现基本数据类型的数据劫持。
ES6 Proxy 代理
Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义
ES6 Reflect 反射
Reflect是ES6为了操作对象而新增的API。
Reflect继承Object
Reflect.__proto__ === Object.prototype
Reflect与Object类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与Proxy是对应得
ES6中将Object的一些明显属于语言内部的方法移植到Reflect对象上(当前某些方法会同时存在于Object和Reflect对象上),未来的新方法会只部署在Reflect对象上。
Reflect对象对某些方法的返回结果进行了修改,使其更合理。
Reflect对象使用函数的方式实现了Object的命令式操作。
Reflect.set(target, propertyKey, value[, receiver])
-
target 设置属性的目标对象
-
propertyKey 设置的属性的名称
-
value 设置的值
-
receiver 如果目标对象上有setter,receiver则为setter调用时的this值。
//反射
var obj = {
a: 1,
set : function(a){
this.a = a
}
}
var receiver = {
a : 2
}
Reflect.set(obj, 'a', 11)
console.log(obj.a)
console.log(receiver.a)
Reflect.set(obj, 'a', 3, receiver)
console.log(obj.a)
console.log( receiver.a)