响应式最基本的理解就是可以自动响应数据变化的代码机制。
比如:下面这段代码,初始化了一个m变量,第2行代码使用了m,那么在m有一个新值得时候,第2行代码要可以自动重新执行。
示例1:
javascriptlet m = 20
console.log(m)
m = 40
对象的响应式
javascript// 响应式对象
let obj = {
name: 'yjw'
}
// 打印obj.name
coneole.log(obj.name)
// 改变obj是应该重新打印obj.name
obj.name = 'null'
在vue中最直接的体现就是watch、reactive函数了
javascriptwatch: {
data(){
console.log('data发生了变化')
}
}
javascript// 保存当前需要收集的响应式函数
let activeReactiveFn = null;
class Depend {
constructor() {
// 使用Set来保存依赖函数, 而不是数组[]
this.reactiveFns = new Set();
}
notify() {
this.reactiveFns.forEach((fn) => {
fn();
});
}
depend() {
if (activeReactiveFn) {
this.reactiveFns.add(activeReactiveFn);
}
}
}
// WeakMap({key(对象): value}), key是个对象,弱引用(当将key设置为null时,key被垃圾回收机制回收,对应的value也会被回收)
const targetMap = new WeakMap();
// 封装一个获取depend函数
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;
}
// 封装一个响应式的函数
function watchEffect(fn) {
activeReactiveFn = fn;
fn();
activeReactiveFn = null;
}
function reactive(obj) {
const keys = Object.keys(obj);
keys.forEach((key) => {
let value = obj[key];
Object.defineProperty(obj, key, {
get() {
// 做依赖收集
const depend = getDepend(obj, key);
depend.depend();
return value;
},
set(newValue) {
value = newValue;
// 监听对象变化做出响应
const depend = getDepend(obj, key);
depend.notify();
},
});
});
return obj
}
测试
javascriptconst objProxy = reactive({
name: 'yjw',
age: 22
})
watchEffect(function() {
console.log('模拟watch1----, name属性发生变化')
objProxy.name
console.log('do Somethings1')
})
watchEffect(function() {
console.log('模拟watch2----,age属性发生变化')
objProxy.age
console.log('do Somethings2')
})
console.log('-----------------------------')
objProxy.name = 'coder'
objProxy.age = 18
只要把reactive中Object.defineProperty实现换成Proxy就行了
javascript// 保存当前需要收集的响应式函数
let activeReactiveFn = null
class Depend {
constructor() {
// 使用Set来保存依赖函数, 而不是数组[]
this.reactiveFns = new Set()
}
notify() {
this.reactiveFns.forEach(fn => {
fn()
})
}
depend() {
if(activeReactiveFn) {
this.reactiveFns.add(activeReactiveFn)
}
}
}
const targetMap = new WeakMap()
// 封装一个获取depend函数
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
}
// 封装一个响应式的函数
function watchEffect(fn) {
activeReactiveFn = fn
fn()
activeReactiveFn = null
}
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
// 根据target.key获取对应的depend
// 做依赖收集
const depend = getDepend(target, key)
depend.depend()
return Reflect.get(target, key, receiver)
},
set(target, key, newValue , receiver) {
Reflect.set(target, key, newValue, receiver)
// 监听对象变化做出响应
const depend = getDepend(target, key)
depend.notify()
}
})
}
测试
javascriptconst objProxy = reactive({
name: 'yjw',
age: 22
})
watchEffect(function() {
console.log('模拟watch1----, name属性发生变化')
objProxy.name
console.log('do Somethings1')
})
watchEffect(function() {
console.log('模拟watch2----,age属性发生变化')
objProxy.age
console.log('do Somethings2')
})
console.log('-----------------------------')
objProxy.name = 'coder'
objProxy.age = 18
本文作者:叶继伟
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!