记jQuery.fn.show的一次踩坑和问题排查
2015-11-12 12:09
621 查看
最近很少已经很少用jQuery,因为主攻移动端,常用Zepto,其实很多细节和jQuery并不一样。最近又无意中接触到了PC的需求和IE6, 使用了jQuery,刚好踩坑了,特意记录一下。
本文内容如下:
问题
解决
jQuery.fn.show()和jQuery.fn.show(0)到底发生了什么
结语
参考和引用
JavaScript - 前端开发交流群:377786580
一直只记得jQuery.fn.show/jQuery.fn.hide方法在后来被改写过,也没怎么去关注过这里,最近又无意中接触到了PC的需求和IE6, 使用了jQuery,刚好踩坑了,特意记录一下。
问题就是有一个<a>标签默认是隐藏的(display:none),做了一些业务逻辑的处理之后呢把这个<a>显示出来(通过jQuery.fn.show),但是这个<a>标签却被加上了新的样式:
查了一下当时调用
其实是自己对jQuery.fn.show/jQuery.fn.hide记错了,以前学jQuery的时候就只记得了个jQuery动画有个默认的时间,是300ms。但没记API,其实是:
jQuery的动画系列函数,
参见jQuery 1.11.0源码:
合并动画配置(设置动画默认时间)的代码是
后来查到问题是给方法传递了一个参数
然后被妹子追问为什么,回答不上来,只记得这俩API后来调整过。
刚开始我仍然天真的以为jQuery.fn.show在不传递参数的情况下会有默认动画时间,直到翻阅源码版本至jQuery 1.4.0发现都对没有参数的情况进行了display的处理,反而是传递了
在jQuery 1.11.0代码整理后阅读起来好了很多:
可以看见当在jQuery 1.11.0中,当speed参数为null、undefined、boolean的时候会进入css直接处理分支,而不会走动画。
所以下面的代码完全走的是不同的分支:
那么<a>上的
到了这里再想想动画的一些操作因素,也就可以理解为什么会这样了:
jQuery中的动画操作的无非是位置、透明度、宽高几个点。
有些动画涉及到宽高的改变(例如:jQuery.fn.show/jQuery.fn.hide改变的就是元素的width+height,jQuery.fn.slideDown改变的是height),那么就需要把这些元素设置成可以改变宽高的(行)块级元素。因为行级元素是不能通过css改变宽高的。
而<a>标签默认是inline的,当对它操作width/height(即jQuery.fn.show)的时候,需要把它改成inline-block,让动画对它设置的宽高生效。
加这一个参数和不加参数光看看源码就知道是天壤之别了,更别提什么性能,IE678套餐可能造成的影响了。
其实问题的根源仍然在于我对代码的了解程度不够,对于当前代码的认知自己竟然觉得满足了。想想刚学js的我可是充满了好奇心各种探索造轮子查资料读源码,随着时间的推移,技术实力和视野逐渐的提升,让自己变得越来越懒惰,越来越容易满足,这样的状态并不好。
任何时候,都应该清楚的知道自己撸的代码到底发生了什么,学无止境,共勉。
JavaScript - 前端开发交流群:377786580
作者:linkFly原文:http://www.cnblogs.com/silin6/p/jQuery-fn-show.html出处:www.cnblogs.com/silin6/声明:嘿!你都拷走上面那么一大段了,我觉得你应该也不介意顺便拷走这一小段,希望你能够在每一次的引用中都保留这一段声明,尊重作者的辛勤劳动成果,本文与博客园共享。
本文内容如下:
问题
解决
jQuery.fn.show()和jQuery.fn.show(0)到底发生了什么
结语
参考和引用
JavaScript - 前端开发交流群:377786580
问题
最近很少用jQuery,因为主攻移动端,常用Zepto,其实很多细节和jQuery并不一样。以前读过Zepto的源码,所以完全知道zepto.fn.show/zepto.fn.hide到底做了什么。一直只记得jQuery.fn.show/jQuery.fn.hide方法在后来被改写过,也没怎么去关注过这里,最近又无意中接触到了PC的需求和IE6, 使用了jQuery,刚好踩坑了,特意记录一下。
问题就是有一个<a>标签默认是隐藏的(display:none),做了一些业务逻辑的处理之后呢把这个<a>显示出来(通过jQuery.fn.show),但是这个<a>标签却被加上了新的样式:
<a href="javascript:;" style="display:inline-block;"></a>
查了一下当时调用
jQuery.fn.show的代码:
$('#id').show(0); //给a加上了display:inline-block;
解决
触发这个问题就是因为自己错误的以为jQuery.fn.show/jQuery.fn.hide会有默认动画时间,于是显示隐藏元素的时候喜欢这样处理:
$('#id').show(0); $('#id').hide(0);
其实是自己对jQuery.fn.show/jQuery.fn.hide记错了,以前学jQuery的时候就只记得了个jQuery动画有个默认的时间,是300ms。但没记API,其实是:
jQuery的动画系列函数,
slideDown、slideUp、slideToggle、fadeIn、fadeOut、fadeToggle、fadeTo、toggle都是默认400ms动画时间的,而
show/hide默认是没有动画时间的。
参见jQuery 1.11.0源码:
jQuery.each({ slideDown: genFx("show"), slideUp: genFx("hide"), slideToggle: genFx("toggle"), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide" }, fadeToggle: { opacity: "toggle" } }, function( name, props ) { jQuery.fn[ name ] = function( speed, easing, callback ) { return this.animate( props, speed, easing, callback ); }; });
合并动画配置(设置动画默认时间)的代码是
jQuery.speed方法:
jQuery.speed = function( speed, easing, fn ) { var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { complete: fn || !fn && easing || jQuery.isFunction( speed ) && speed, duration: speed, easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing }; opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default /*默认动画时间(ms)*/; if ( opt.queue == null || opt.queue === true ) { opt.queue = "fx"; } opt.old = opt.complete; opt.complete = function() { if ( jQuery.isFunction( opt.old ) ) { opt.old.call( this ); } if ( opt.queue ) { jQuery.dequeue( this, opt.queue ); } }; return opt; }; //... jQuery.fx.speeds = { slow: 600, fast: 200, // Default speed _default: 400 };
后来查到问题是给方法传递了一个参数
0导致的问题,把参数去掉即可,改成下面的代码即可:
<script> $('#id').show(); </script> <a href="javascript:;" style=""></a>
然后被妹子追问为什么,回答不上来,只记得这俩API后来调整过。
jQuery.fn.show()和jQuery.fn.show(0)到底发生了什么
之后我就觉得有必要再去深入了解下jQuery.fn.show/jQuery.fn.hideAPI了,至少要了解下这俩API现在到底做了什么。刚开始我仍然天真的以为jQuery.fn.show在不传递参数的情况下会有默认动画时间,直到翻阅源码版本至jQuery 1.4.0发现都对没有参数的情况进行了display的处理,反而是传递了
speed之后会走动画处理。
jQuery.fn.extend({ //$('id').show(); show: function( speed, callback ) { if ( speed != null ) { return this.animate( genFx("show", 3), speed, callback); } else { //speed===undefined for ( var i = 0, l = this.length; i < l; i++ ) { //操作元素的display var old = jQuery.data(this[i], "olddisplay"); this[i].style.display = old || ""; if ( jQuery.css(this[i], "display") === "none" ) { var nodeName = this[i].nodeName, display; if ( elemdisplay[ nodeName ] ) { display = elemdisplay[ nodeName ]; } else { var elem = jQuery("<" + nodeName + " />").appendTo("body"); display = elem.css("display"); if ( display === "none" ) { display = "block"; } elem.remove(); elemdisplay[ nodeName ] = display; } jQuery.data(this[i], "olddisplay", display); } } for ( var j = 0, k = this.length; j < k; j++ ) { this[j].style.display = jQuery.data(this[j], "olddisplay") || ""; } return this; } }, hide: function( speed, callback ) { if ( speed != null ) { return this.animate( genFx("hide", 3), speed, callback); } else { for ( var i = 0, l = this.length; i < l; i++ ) { var old = jQuery.data(this[i], "olddisplay"); if ( !old && old !== "none" ) { jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display")); } } for ( var j = 0, k = this.length; j < k; j++ ) { this[j].style.display = "none"; } return this; } } });
在jQuery 1.11.0代码整理后阅读起来好了很多:
jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { var cssFn = jQuery.fn[ name ]; jQuery.fn[ name ] = function( speed, easing, callback ) { //$('#id').show(); //speed===undefined return speed == null || typeof speed === "boolean" ? cssFn.apply( this, arguments ) : this.animate( genFx( name, true ), speed, easing, callback ); }; });
可以看见当在jQuery 1.11.0中,当speed参数为null、undefined、boolean的时候会进入css直接处理分支,而不会走动画。
所以下面的代码完全走的是不同的分支:
$('#id').show(); //走css处理分支 $('id').show(0); //走animate处理分支
那么<a>上的
display:inline-block从何而来呢?于是搜索了一下
inline-block,发现了这一段代码:
function defaultPrefilter( elem, props, opts ) { /* jshint validthis: true */ var prop, value, toggle, tween, hooks, oldfire, display, dDisplay, anim = this, orig = {}, style = elem.style, hidden = elem.nodeType && isHidden( elem ), dataShow = jQuery._data( elem, "fxshow" ); // ... // height/width overflow pass if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; display = jQuery.css( elem, "display" ); //获取元素样式中的display dDisplay = defaultDisplay( elem.nodeName ); //获取元素默认的display if ( display === "none" ) { display = dDisplay; } if ( display === "inline" && jQuery.css( elem, "float" ) === "none" ) { if ( !support.inlineBlockNeedsLayout || dDisplay === "inline" ) { //现代浏览器下,当元素默认的display为inline,则调整为inline-block style.display = "inline-block"; } else { style.zoom = 1; } } } // ... }
defaultPrefilter方法在jQuery内置的动画对象
Animation中调用,用于修正执行动画前的一些细节。
到了这里再想想动画的一些操作因素,也就可以理解为什么会这样了:
jQuery中的动画操作的无非是位置、透明度、宽高几个点。
有些动画涉及到宽高的改变(例如:jQuery.fn.show/jQuery.fn.hide改变的就是元素的width+height,jQuery.fn.slideDown改变的是height),那么就需要把这些元素设置成可以改变宽高的(行)块级元素。因为行级元素是不能通过css改变宽高的。
而<a>标签默认是inline的,当对它操作width/height(即jQuery.fn.show)的时候,需要把它改成inline-block,让动画对它设置的宽高生效。
结语
至此,问题追查完毕,我也可以好好的跟妹子吹吹牛逼啦~~~~~~~当然除了这个,更多的是自己的反思,想起了之前做的代码里很多时候使用的都是:$('#id').show(0);
加这一个参数和不加参数光看看源码就知道是天壤之别了,更别提什么性能,IE678套餐可能造成的影响了。
其实问题的根源仍然在于我对代码的了解程度不够,对于当前代码的认知自己竟然觉得满足了。想想刚学js的我可是充满了好奇心各种探索造轮子查资料读源码,随着时间的推移,技术实力和视野逐渐的提升,让自己变得越来越懒惰,越来越容易满足,这样的状态并不好。
任何时候,都应该清楚的知道自己撸的代码到底发生了什么,学无止境,共勉。
JavaScript - 前端开发交流群:377786580
作者:linkFly原文:http://www.cnblogs.com/silin6/p/jQuery-fn-show.html出处:www.cnblogs.com/silin6/声明:嘿!你都拷走上面那么一大段了,我觉得你应该也不介意顺便拷走这一小段,希望你能够在每一次的引用中都保留这一段声明,尊重作者的辛勤劳动成果,本文与博客园共享。
相关文章推荐
- JQuery 禁用所有select标签的值
- JQuery按照指定长度为数字前面补零
- JQuery的Ajax使用Get,Post方法调用C#WebService并返回数据
- jQuery提交Json数据到Webservice,并接收返回的Json数据
- jQuery仿google搜索下拉列表 支持键盘上下键 支持鼠标移动
- Jquery如何获取ASP.NET服务器控件的值
- jQueryEasyUI Messager基本使用
- Jquery AutoComplete自动完成 的使用方法实例22
- jquery 定义工具类写法
- jQuery:表格的奇偶行变色,jquery实例之表格隔一行
- jquery编写弹窗
- Jquery实现省市县三级联动
- jQuery基础知识总结
- jQuery 指定context 嵌套匹配
- Jquery的$命名冲突:
- 用JQuery怎么去一次性获取 aspTextBox 文本框的值
- Jquery 函数重载及常见bug
- jQuery自定义插件
- 基于jquery实现左右按钮点击的图片切换效果
- jquery开发自定义的插件总结