data函数在jquery中只有短短的300行代码,非常不起点 ,剖析源码的时候你会发现jQuery只要在有需要保存数据的地方无时无刻不依赖这个基础设施
动画会调用队列,队列会调用data数据接口还保存队列里面的的动画数据
所以我们在自习回顾下关于数据缓存
data在jQuery中有两种
一个是用来存数据的, 对应的对象分别是
另一个是用来存事件的,动画数据的
data_user
和data_priv
, 就如其名, 一个是用户用的, 一个是jQuery私有的, 他们都是一个叫Data的实例对象
为什么要设置这2个数据接口类?
jQuery的设置都是维护一个jQuery的数据对象,所以
只是实现data的接口,比如:
实现链式的.data接口,这种很简单,我们可以把简单的数据缓存到jquery内部的这个对象上
方法可以这样实现
直接在实例上fn的接口上扩充
这个很简单把数据直接保存在dom对象上
当然针对基本类型这样处理当然也是可以的,如果是引用类型,函数对象呢?这样处理可以吗?
问题来了:
1:这样会更改DOM本身的属性值,当然能不能生效还不说
2:传递可是引用类型哦,不靠谱的内存回收,说不定就溢出了
3:数据暴露,容易被直接改写
如何解决这些问题? jQuery就引入了数据对象这个概念
先不管内部怎么实现,先看节点的属性
多了一个灰色的自定义的key与value
灰色意味着不能通过for枚举出来,这种设置在ES5中,是有API直接支持了
看注释就清晰了,这个属性是受保护的,不能被改写
OK了。通过这样一个唯一的桥接标志,我们可以做一个ORM的映射了,让dom与一个数据缓存接口产生一一对应的关系
动画队列用到的数据缓存
jQuery为了实现动画队列的链式调用,所以必须先在实例就是原型上先扩展一个方法啊,然后在内部才能调用底层的方法
当然jQuery基本所有的层次都是这样的结构,除了链式之外,还可以把具体的实例方法与原型方法通用
动画的实例方法
调用实例方法中基于动画的扩展接口
实例的queue接口只是做了2个情况的判断,一种是传递fx,一种是设置队列,底层还是通过jQuery.queue静态方法处理的
分析一组动画:
1 有时间参数的接口,是肯定需要执行动画的,同一个接口上有多个动画接口,那么就会意味着需要队列来管理执行顺序
2 管理队列引入数据缓存,缓存需要载体node节点,所以动画的扩展的接口在最上层设计是可以直接跟DOM链式
逻辑上肯定是线性的执行,show执行完毕,然后取出hide执行,完毕后在取出show执行
那么动画的调用是如何组织的?
理论上3个动画,在cache中有3个缓存的data我们查看下
为了便于查看,我把代码改了下 增加了一个标示 Aaron 对应的是时间
在执行div.show(3000)的时候,我们查看下缓存
发现0位置的div.show(1000);被inprogress给替代了
可以猜测下第一个动画已经在开始执行了,那么它在队列中会用一个占位符用来通知后面,我这个动画还在进行,后面的动画先等等
inprogress”进程锁是这样工作的:
如果是dequeue操作, 去掉锁, 执行队列里的函数, 同时给队列加上锁. 如果是queue操作, 要看锁的状态, 如果被锁上了, 就只执行队列的添加操作. 不再调用dequeue.其实dequeue和queue都可以执行队列里的第一个函数.queue操作添加完队列之后, 会调用dequeue方法去执行函数.
用dequeue执行函数的时候, 这时候如果又用queue触发dequeue的话, 很可能同时有2个函数在执行. 队列就失去一大半意义了(还是可以保证顺序, 但是2个动画会同时执行).不过这个锁只能保证在dequeue的时候, 不被queue操作意外的破坏队列.
如果人为的同时用2个dequeue, 还是会破坏动画效果的. 所以要把fn写在回调函数里
我们在第一次做push的时候就会开始执行了动画,这样可以让速度更优
.queue(1000) , .queue(2000) , queue(3000)
当第一个动画执行完毕后,那么必须有一个回调通知这个去把队列中下一个执行给取出来,然后要删掉这个占位,依次循环
所以可见,动画的执行其实最终是依赖queue与dequeue的处理,只是说在执行开始与执行完毕做了一个流程的控制
具体动画内部怎么执行的,从下章开始分析
- 海报