内容简介:在上一篇我们大概实现了,首先我们可以先确定这个类下的属性,以及一些功能:类下属性:
在上一篇我们大概实现了, Vue
中的依赖收集和触发,但我们仅仅是将依赖维护在一个内置数组中,这样做虽然容易理解,但毕竟不好维护,为了更容易的维护这些依赖,我们来实现一个维护依赖的类。
确定功能
首先我们可以先确定这个类下的属性,以及一些功能:
类下属性:
- target 函数,用于存放需要添加的依赖
实例下属性及方法:
- subs/Array 用于存放依赖
- addSub/Function 用于添加依赖
- removeSub/Function 用于移除依赖
- notify/Function 用于执行依赖
实现
考虑到直接放在浏览器上执行,所以直接用 ES5
的类写法。
let Dep = function(){
// 实例属性
this.subs = []
// 实例方法
this.addSub = function(sub){
this.subs.push(sub)
}
this.removeSub = function(sub){
const index = this.subs.indexOf(item)
if (index > -1) {
this.subs.splice(index, 1)
}
}
this.notify = function(newValue, oldVaule){
this.subs.forEach(fnc=>fnc(newValue, oldVaule))
}
}
// 类属性
Dep.target = null
复制代码
好了,现在我们拥有了一个管理依赖的类(这里将依赖简化为一个方法),现在我们就可以动手来改一下之前的代码了。
let defineReactive = function(object, key, value){
let dep = new Dep()
Object.defineProperty(object, key, {
configurable: true,
enumerable: true,
get: function(){
if(Dep.target){
dep.addSub(Dep.target)
}
return value
},
set: function(newValue){
if(newValue != value){
dep.notify(newValue, value)
}
value = newValue
}
})
}
复制代码
可以发现,之前我们用来存放依赖的数组变成了一个依赖管理( Dep
)的实例。同样的,在取值时收集依赖,在设置值(当值发生变化)时触发依赖。
由于依赖的处理由 Dep
的实例管理了,这里仅仅调用一下相关方法即可。
接下来试一试效果:
let object = {}
defineReactive(object, 'test', 'test')
Dep.target = function(newValue, oldValue){
console.log('我被添加进去了,新的值是:' + newValue)
}
object.test
// test
Dep.target = null
object.test = 'test2'
// 我被添加进去了,新的值是:test2
Dep.target = function(newValue, oldValue){
console.log('添加第二个函数,新的值是:' + newValue)
}
object.test
// test
Dep.target = null
object.test = 'test3'
// 我被添加进去了,新的值是:test3
// 添加第二个函数,新的值是:test3
复制代码
但是上面的代码暴露了几个问题
-
Dep这个类将监听属性和处理依赖进行了解耦,但是却没有完全解耦,在触发依赖的时候,还是得传新旧值。 -
上面代码中
Dep中定义的removeSub在代码中并没有用到,因为Dep的实例是在defineReactive函数的作用域中,外部并不能直接调用,而删除依赖肯定是在外部的环境中,也就是说即使我们将代码改成这样,我们还是不能直接取删除已经没用的依赖。
Vue
中实现了一个 Watcher
的类来处理以上两个问题,之后再说。
以下 ES6
语法下的 Dep
, Vue
源码中差不多就这样
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
removeSub(sub) {
const index = this.subs.indexOf(item)
if (index > -1) {
this.subs.splice(index, 1)
}
}
notify() {
this.subs.forEach(fnc=>fnc(oldValue, newValue))
}
}
Dep.target = null
复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- php如何实现session,自己实现session,laravel如何实现session
- AOP如何实现及实现原理
- webpack 实现 HMR 及其实现原理
- Docker实现原理之 - OverlayFS实现原理
- 为什么实现 .NET 的 ICollection 集合时需要实现 SyncRoot 属性?如何正确实现这个属性?
- 自己实现集合框架(十):顺序栈的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Adobe Dreamweaver CS5中文版经典教程
Adobe公司 / 陈宗斌 / 人民邮电 / 2011-1 / 45.00元
《Adobe Dreamweaver CS5中文版经典教程》由Adobe公司的专家编写,是AdobeDreamweavelCS5软件的官方指定培训教材。全书共分为17课,每一课先介绍重要的知识点,然后借助具体的示例进行讲解,步骤详细、重点明确,手把手教你如何进行实际操作。全书是一个有机的整体,它涵盖了Dreamweavercs5的基础知识、HTML基础、CSS基础、创建页面布局、使用层叠样式表、使......一起来看看 《Adobe Dreamweaver CS5中文版经典教程》 这本书的介绍吧!