mootools fade方法的一个小陷阱

用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');
		});

 这样问题就解决了...

posted @ 2011-12-11 00:29  MrPrime  阅读(566)  评论(0编辑  收藏  举报