一、对象的监听方式
1.1 vue2中监听对象:Object.defineProperty(obj,key,descriptor)
vue2中使用Object.defineProperty来进行对象的监听:
//先定义一个对象
const obj = {
age:16,
height:1.88,
grade:99
}
//遍历对象,对每个属性进行监听
Object.keys(obj).forEach(key => {
let value = obj[key]
Object.defineProperty(obj,key,{
//通过存取属性描述符进行操作
get() {
console.log(`${key}属性被访问了`);
return value
},
set(newValue) {
console.log(`${key}属性被赋值了`);
if (value === newValue) return
value = newValue
}
})
})
obj.age
obj.height = 2.0
但是通过这种方法会有一些缺点:首先,Object.defineProperty设计的初衷不是为了去监听一个对象中 所有的属性的;其次,如果我们想监听更加丰富的操作,比如新增属性、删除属性,那么 Object.defineProperty是无能为力的。
那么我们怎样能正确监听对象呢?在ES6中,新增了proxy类,如果我们监听一个对象的相关操作,那么我们可以先创建一个代理对象(proxy对象),之后对该对象的所有操作,都通过代理对象来完成。
1.2 vue3中监听对象:const proxyObj = new Proxy(target, handler)
vue3中通过Proxy类创建一个代理对象,之后的操作都是直接对代理对象的操作,而不是原有对象:
//先定义一个对象
const obj = {
name: 'why',
age: 20,
height:1.98
}
//创建代理对象
//参数:
//target(侦听的对象obj)、key(将被设置的属性)、value(新属性的值)、receiver(调用的代理对象objProxy )
const objProxy = new Proxy(obj, {
get(target, key, receiver) {
console.log(`对象的${key}属性被访问`,target);
// return target[key]
return Reflect.get(target,key,receiver)
},
set(target, key, value, receiver) {
if (target[key] !== value) {
// target[key] = value
Reflect.set(target,key,value,receiver)
console.log(`对象的${key}属性被设置值`,target);
}
},
has(target, key) {
// return key in target
return Reflect.has(target,key)
},
deleteProperty(target, key) {
// delete target[key]
Reflect.deleteProperty(target,key)
}
})
console.log(objProxy.name);
console.log(objProxy.age);
objProxy.name = 'kobe'
objProxy.age = 20
console.log('name' in objProxy);
delete objProxy.height
console.log(objProxy);
上面代码中使用了Reflect对象,如果不了解Reflect对象的,点击了解Reflect
二、实现响应式原理
2.1 vue2实现响应式
//1.定义一个全局函数对象,用来保存依赖函数
let activeReactiveFn = null
//2.定义一个监听函数
function watchFn(fn) {
activeReactiveFn = fn
fn()
activeReactiveFn = null
}
//3.定义一个类,用来给对象的每个属性添加对应的依赖函数,还有执行函数
class Depend {
constructor() {
this.reactiveFns = new Set()
}
//添加依赖函数
addDepend() {
if (activeReactiveFn) {
this.reactiveFns.add(activeReactiveFn)
}
}
//执行依赖函数
notify() {
this.reactiveFns.forEach(fn => {
fn()
})
}
}
//4.创建一个weakMap,用来储存多个对象的多个属性对应的依赖
const targetMap = new WeakMap()
function getDepend(target, key) {
// 根据target对象获取map的过程
let map = targetMap.get(target)
if (!map) {
map = new Map()
targetMap.set(target, map)
}
// 根据key获取depend对象
let depend = map.get(key)
if (!depend) {
depend = new Depend()
map.set(key, depend)
}
return depend
}
//注:vue2和vue3监听对象主要区别
// 5、对对象进行监听,并返回监听后的对象
function reactive(obj) {
Object.keys(obj).forEach(key => {
const value = obj[key]
Object.defineProperty(obj, key, {
get() {
const depend = getDepend(obj, key)
depend.addDepend()
return value
},
set(newValue) {
value = newValue
const depend = getDepend(obj, key)
depend.notify()
}
})
})
return obj
}
//6、定义一个对象
const obj = {
name: "why",
age: 18
}
// 7、调用函数对对象进行监听
reactive(obj)
//8、收集对象的属性监听时所触发的函数
watchFn(() => {
console.log(obj.name, '监听对象obj的name属性');
})
watchFn(() => {
console.log(obj.age, '监听对象obj的age属性');
})
//9、对对象进行操作
obj.name = 'code'
obj.age = 22
2.2 vue3实现响应式
//1.定义一个全局函数对象,用来保存依赖函数
let activeReactiveFn = null
//2.定义一个监听函数
function watchFn(fn) {
activeReactiveFn = fn
fn()
activeReactiveFn = null
}
//3.定义一个类,用来给对象的每个属性添加对应的依赖函数,还有执行函数
class Depend {
constructor() {
this.reactiveFns = new Set()
}
//添加依赖函数
addDepend() {
if (activeReactiveFn) {
this.reactiveFns.add(activeReactiveFn)
}
}
//执行依赖函数
notify() {
this.reactiveFns.forEach(fn => {
fn()
})
}
}
//4.创建一个weakMap,用来储存多个对象的多个属性对应的依赖
const targetMap = new WeakMap()
function getDepend(target, key) {
// 根据target对象获取map的过程
let map = targetMap.get(target)
if (!map) {
map = new Map()
targetMap.set(target, map)
}
// 根据key获取depend对象
let depend = map.get(key)
if (!depend) {
depend = new Depend()
map.set(key, depend)
}
return depend
}
//注:vue2和vue3监听对象主要区别
// 5、创建代理对象函数
//参数:
//target(侦听的对象obj)、key(将被设置的属性)、value(新属性的值)、receiver(调用的代理对象objProxy )
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
// 根据target.key获取对应的depend
const depend = getDepend(target, key)
// 给depend对象中添加响应函数
depend.addDepend()
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
const depend = getDepend(target, key)
depend.notify()
}
})
}
//6、定义一个对象
const obj = {
name: "why",
age: 18
}
// 7、通过函数创建代理对象
const objProxy = reactive(obj)
//8、监听代理对象的属性时所触发的函数
watchFn(() => {
console.log(objProxy.name, '监听代理对象objProxy的name属性');
})
watchFn(() => {
console.log(objProxy.age, '监听代理对象objProxy的age属性');
})
//9、对代理对象进行操作
objProxy.name = 'code'
objProxy.age = 22
73

被折叠的 条评论
为什么被折叠?



