您的位置:首页 > 娱乐 > 明星 > 非标自动化外包平台_南通企业免费建站_地推团队如何收费_百度助手官网

非标自动化外包平台_南通企业免费建站_地推团队如何收费_百度助手官网

2024/12/26 21:07:19 来源:https://blog.csdn.net/qq_27702739/article/details/143996515  浏览:    关键词:非标自动化外包平台_南通企业免费建站_地推团队如何收费_百度助手官网
非标自动化外包平台_南通企业免费建站_地推团队如何收费_百度助手官网

数据要在获取时收集依赖,在设置时触发更新依赖,核心方法defineReactive

function defineReactive(data, key, value) {// 存放依赖的数组let dep = []Object.defineProperty(data, key, {enumerable: true,configurable: true,get() {// 收集依赖,这个依赖就是挂载在全局上的方法dep.push(window.target)return value},set(newValue) {if (val === newValue) return// 赋值时,更新所有的依赖for (let i = 0; i < dep.length; i++) {dep[i](newValue, val)}val = newValue}})
}

封装的收集依赖的辅助方法

class Dep {constructor() {this.subs = []}addSub(sub) {this.subs.push(sub)}removeSub(sub) {remove(this.subs, sub)}depend() {if (window.target) {this.addSub(window.target)}}notify() {const subs = this.subs.slice()for (let i = 0; i < subs.length; i++) {subs[i].update()}}
}function remove(arr, item) {if (arr.length) {let index = arr.indexOf(item)if (index > -1) {return arr.splice(index, 1)}}
}

改写响应式数据劫持的方法

function defineReactive(data, key, value) {let dep = new Dep()Object.defineProperty(data, key, {enumerable: true,configurable: true,get() {dep.depend()return value},set(newValue) {if (val === newValue) returnval = newValuedep.notify()}})
}

依赖谁谁?就是上面的 window.target,那么他到底是啥?其实就是要通知用到这个状态的地方,
它有可能是个模块,也有能是一个 watch,那么我们就需要封装这样一个集中处理不同依赖类型的方法,
我们先通知这个方法,然后这个方法内部再去通知其他地方。Watcher

class Watcher {constructor(vm, expOrFn, cb) {this.vm = vmthis.getter = parsePath(expOrFn)this.cb = cbthis.value = this.get()}get() {window.target = thislet value = this.getter.call(this.vm, this.vm)window.target = undefinedreturn value}update() {const oldValue = this.valuethis.value = this.get()this.cb.call(this.vm, this.value, oldValue)}
}// 解析简单路径
const bailRE = /[^\w.$]/
export function parsePath(path) {if (bailRE.test(path)) return// data.a.b.c => [data,a,b,c]const segment = path.split('.')return function (obj) {for (let index = 0; index < segment.length; index++) {if (!obj) returnconst item = segment[index]obj = obj[item]}return obj}
}

递归把 obj 的所有转化为响应式数据

class Observer {constructor(value) {this.value = valueif (!Array.isArray(value)) {this.walk(value)}}walk(obj) {const keys = Object.keys(obj)for (let index = 0; index < keys.length; index++) {const key = keys[index]defineReactive(obj, key, obj[key])}}
}

修改defineReactive方法,将一个正常的 object 转化为被侦测的 object,其中要判断数据类型,只有是 Object 类型的数据才会调用 walk 方法将每一个属性转化为 getter/setter 的形式来侦测变化

function defineReactive(data, key, value) {// 递归所有的子属性if (typeof val === 'object') {new Observer(val)}let dep = new Dep()Object.defineProperty(data, key, {enumerable: true,configurable: true,get() {dep.depend()return value},set(newValue) {if (val === newValue) returnval = newValuedep.notify()}})
}

关于 Object 中的问题

由于前面的追踪方式局限,导致有些语法即使是数据发生了变化,数据也不会更新

new Vue({el: '#app',template: '<div>xxxx</div>',methods:{actions:{this.obj.name = 'nelsen'}},data:{obj:{}}
})

action 方法中,我们在 obj 上面新增了一个 name 的属性,框架是无法侦测到这个变化的,
所以就不会向依赖发送通知。同理删除一个属性也是同样的

new Vue({el: '#app',template: '<div>xxxx</div>',methods:{actions:{delete this.obj.name}},data:{obj:{name:"nelsen"}}
})

vue2中通过Object.defineProperty来将对象的 key
转化为getter/setter的形式来追踪依赖,但是getter/setter只能追踪到数据是否被修改,无法追踪新增和删除
属性,这是由于js语言的限制,没有提供元编程的能力
为了解决这个问题,框架给我们提供了vm.$setvm.$delete两个api,来处理对象的新增删除属性。

版权声明:

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

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