在掘金上买了一个关于解读vue源码的小册,因为是付费的,所以还比较放心
在小册里看到了关于vue双向绑定和依赖收集的部分,总感觉有些怪怪的,然后就自己跟着敲了一遍。 敲完后,发现完全无法运行, 坑啊, 写书人完全没有测试过。
然后自己完善代码, 越写越发现坑, 问题有些大。。。。。。
最后自己重新实现了一遍,代码较多。 用到观察订阅者模式实现依赖收集, Object.defineProperty()
实现双向绑定
/* 自己写的代码, 实现vue的双向绑定和依赖收集 场景: 多个子组件用到父组件data中的数据, 当父组件data中的此数据发生改变时, 所有依赖它的 子组件全部更新 通常子组件的从父组件中拿取的数据不允许发生改变 */ //订阅者 Dep //一个订阅者只管理一个数据 class Dep { constructor () { this.subs = [] //存放vue组件 } addSubs (sub) { this.subs.push(sub) console.log('add watcher: ', sub._name) } notify () { this.subs.forEach( sub => { //通知vue组件更新 sub.update() }) } } //监听者 //一个vue实例包含一个Watcher实例 class Watcher { // 在实例化Watcher时, 将Dep的target指向此实例, 在依赖收集中使用 // 因为依赖收集是在组件初始化时触发的, 而数据变更后视图相应变更是在初始化后 // 所以让Dep.target指向此实例, 当此vue实例初始化完成后, 再指向下一个正在初始化的vue实例完成依赖收集 constructor (name) { Dep.target = this this._name = name } update () { // 这里模拟视图更新 // 其实还应该让子组件的props相应值与父组件更新的数据同步 console.log("子组件视图更新了..." + this._name) } } //对data中的数据设置读写监听, 并且创建订阅者, 用于收集子组件的依赖和发布 function defineReactive (obj, key, value) { // 对vue实例中data对象的每一个属性都 设置一个订阅者Dep let dep = new Dep() // 第二个vue实例的监听 覆盖了第一个vue实例的监听, 因为引用的obj是同一个 Object.defineProperty(obj, key, { configurable: true, enumerable: true, get () { // 在读此属性时, 将当前 watcher 对象收集到此属性的 dep 对象中 // 在实例化vue时将Dep.target指向当前Watcher // get()依赖收集的时候是vue组件初始化的时候, set()是在初始化后 if (dep.subs.indexOf(Dep.target) === -1) { dep.addSubs(Dep.target) } //return obj[key] 此写法报错 提示栈溢出 原因是无限调用get() return value }, set (newVal) { // 此属性改变时, 通知所有视图更新 if (newVal !== value) { value = newVal dep.notify() } } }) } //接收一个对象作为参数, 将该对象的所有属性调用defineReactive设置读写监听 function observer (obj) { if (!obj || (typeof obj !== 'object')) { return } Object.keys(obj).forEach( key => { defineReactive(obj, key, obj[key]) }) } // 构造函数, 监听 配置options中的data()方法返回的对象的所有属性 的读写 class Vue { constructor (options) { this._name = options.name this._data = options.data // 每个vue组件都是一个vue实例, 在一个页面中有多个vue实例 // 在初始化该vue实例时, new一个Watcher对象, 使Dep.target指向此实例 new Watcher(options.name) // 给data中的数据挂载读写监听 observer(this._data) //模拟vue解析template过程, 获取从父组件传递过来的props //在这里进行依赖收集 this._props = options.props "hello", second: 'world', third: ['啦啦啦'] } let times = 0 // 第一次调用返回的是第一个子组件的从父组件继承的数据(vue中props属性的值) // 第二次调用返回的是第二个子组件的从父组件继承的数据(vue中props属性的值) function getProps () { times++ if (times == 1) { let obj = {first: "", second: ""} Object.keys(obj).forEach( key => { // 如果是对象, 则进行深拷贝 // 这里使用到了父组件的数据, 触发依赖收集 if (data[key] instanceof Object) { obj[key] = JSON.parse(JSON.stringify(data[key])) } else { obj[key] = data[key] } }) return obj } else if (times == 2) { let obj = {first: "", third: ""} Object.keys(obj).forEach( key => { if (data[key] instanceof Object) { obj[key] = JSON.parse(JSON.stringify(data[key])) } else { obj[key] = data[key] } }) return obj } } let vue_root = new Vue({ name: 'vue_root', data, //模拟编译template和实例化vue的过程 //在编译父组件 并且传递参数给子组件时, 将子组件的 watcher 添加进父组件的 dep render () { let vue_1 = new Vue({ name: 'vue_1', data: {}, props: true, render () {} }) let vue_2 = new Vue({ name: 'vue_2', data: {}, props: true, render () {} }) return { vue_1, vue_2 } } }) console.log(vue_root) vue_root._data.first = 'hello hello' // vue_1 和 Vue_2 都依赖此数据, 都更新 vue_root._data.third = "aaa" // 只有 vue_2 依赖到了此数据, 更新
总结
以上所述是小编给大家介绍的vue的双向绑定和依赖收集遇到的坑,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com
暂无评论...
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
2024年11月16日
2024年11月16日
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】