用mootools做项目的过程中发现了mootools fade方法一个比较隐秘的问题. 我们先来还原一下问题出现的场景:
<div id="main1"> test1 </div> <button id="fade1">fade1</button> $('fade1').addEvent('click', function() { $('main1').set('tween', { duration: 300, onComplete: function(el) { el.destroy(); } }).fade('out'); });
我们可以简单的给div#main1一个背景以做观察,注意到onComplete回调方法中的el.destroy(), 以实现div#main1淡出后销毁, 这样写在IE9+,和其他主流浏览器中没有任何问题,但是在IE8及之前版本就会出现报错.定位在fade方法中
if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible'); else fade.chain(function(){ this.element.setStyle('visibility','hidden'); });
以上是代码的一段引用,问题就出在this.element不支持setStyle方法. 而且注意到这个方法通过fade.chain加入到调用链中. 至于调用这个方法出错了,应该就是onComplete调用在此方法前了, 考虑到mootools对DOM操作扩展的方式在低版本的IE和其他主流浏览器的不同, el.destroy()的提前调用对元素的扩展进行了清理,以便垃圾回收, 所以轮到其调用setStyle时,就报“不支持此方法”的错误了.
接下来看如何修正这个问题, 其实销毁的目的已经实现了,元素都没了,hidden不hidden显得没意义.问题是有个报错,用户体验就会打折扣.
再去看源代码,直接看Fx类中哪里fire了complete回调就行,下面是一段代码的引用,来自Fx的stop方法:
stop: function(){ if (this.isRunning()){ this.time = null; pullInstance.call(this, this.options.fps); if (this.frames == this.frame){ this.fireEvent('complete', this.subject); if (!this.callChain()) this.fireEvent('chainComplete', this.subject); } else { this.fireEvent('stop', this.subject); } } return this; },
看if(this.frames == this.frame)这个if分支,就知道答案了,this.callChain()调用的就是上面fade.chain(..)中的方法,在此之前一句就是fire了complete回调事件,传入的参数this.subject就是onComplete中得el. 所以只要把销毁的操作放到chainComplete回调中就可以了.
<div id="main2"> test2 </div> <button id="fade2">fade2</button> $('fade2').addEvent('click', function() { $('main2').set('tween', { duration: 300, onChainComplete: function(el) { el.destroy(); } }).fade('out'); });
这样问题就解决了...