您的位置:首页 > 健康 > 养生 > 网络运维工程师工资_青岛网站建设公司效果_高端企业建站公司_什么平台可以免费推广产品

网络运维工程师工资_青岛网站建设公司效果_高端企业建站公司_什么平台可以免费推广产品

2025/1/4 11:12:15 来源:https://blog.csdn.net/2401_84715637/article/details/144749771  浏览:    关键词:网络运维工程师工资_青岛网站建设公司效果_高端企业建站公司_什么平台可以免费推广产品
网络运维工程师工资_青岛网站建设公司效果_高端企业建站公司_什么平台可以免费推广产品

  往期内容:

《Vue进阶教程》第十六课:深入完善响应式系统之单例模式

《Vue进阶教程》第十七课:支持分支切换

《Vue进阶教程》第十八课:避免死循环

《Vue进阶教程》第十九课:computed初步实现

《Vue进阶教程》第二十课:lazy懒执行

《Vue进阶教程》第二十一课:支持缓存

《Vue进阶教程》第二十二课:自定义更新(调度器)

《Vue进阶教程》第二十三课:渲染计算属性的结果

《Vue进阶教程》第二十四课:优化

《Vue进阶教程》第二十五课:watch基本概念

《Vue进阶教程》第二十六课:实现侦听函数

1) 基本实现

如果第一个参数不是副作用函数, 可以将其包装成一个副作用函数

function watch(source, cb) {let getterif (typeof source === 'function') {getter = source} else {getter = () => source}effect(getter, {scheduler() {cb()},})
}

由于并没有触发代理对象的取值操作, 因此不会收集依赖

考虑实现一个函数, 遍历访问source中的每一个属性

function traverse(value) {for (const k in value) {// 将代理对象的每个属性访问一次value[k]}
}
function watch(source, cb) {let getterif (typeof source == 'function') {getter = source} else {getter = () => traverse(source)}effect(getter, {scheduler() {cb()},})
}

2) 支持嵌套

如果代理对象中存在嵌套情况

  1. 在reactive中要递归为嵌套的对象创建代理
  2. 在traverse中要递归访问嵌套的属性

示例

get(target, key) {if (key == '__v_isReactive') return true // 新增// console.log(`自定义访问${key}`)// 收集依赖track(target, key)if (typeof target[key] == 'object') {// 递归处理对象类型return reactive(target[key])}return target[key]
},
function traverse(value) {for (const k in value) {if (typeof value[k] == 'object') {traverse(value[k])} else {// 将代理对象的每个属性访问一次value[k]}}
}

3) 解决循环引用问题

如果按上述写法, 会出现递归循环引用, 陷入死循环

什么是循环引用

如果一个对象的某个属性引用自身, 在递归时会死循环

问题示例

const state = reactive({ name: 'xiaoming', address: { city: '武汉' } })
state.test = state// watch接收响应式对象的情况
watch(state, () => {console.log('该函数默认不执行, 只有状态更新时执行...')
})setTimeout(() => {// 侦听对象时, 是深度侦听state.address.city = '北京'
}, 1000)

以上问题可以简化为

const obj = {foo: 'foo',
}
// obj的一个属性引用obj本身, 出现循环引用问题
obj.bar = objfunction traverse(value) {for (const k in value) {if (typeof value[k] == 'object') {traverse(value[k])} else {// 将代理对象的每个属性访问一次value[k]}}
}traverse(obj)

为了避免递归循环引用陷入死循环, 改造traverse方法

function traverse(value, seen = new Set()) {// 如果这个对象已经被遍历过了, 直接返回if (typeof value !== 'object' || seen.has(value)) return// 将遍历的对象记录下来, 再递归时判断seen.add(value)for (let key in value) {// 这里取值, 会触发proxy对象的getter操作traverse(value[key], seen)}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com