通过阅读源码我们发现show,hide,toggle调用了showHide和isHidden这2个方法,所以我们要搞明白原理必须先看一下这2个方法。

jQuery.fn.extend({

        .................

    show: function() {
return showHide( this, true );
},
hide: function() {
return showHide( this );
},
toggle: function( state, fn2 ) {
var bool = typeof state === "boolean"; if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
return eventsToggle.apply( this, arguments );
} return this.each(function() {
if ( bool ? state : isHidden( this ) ) {
jQuery( this ).show();
} else {
jQuery( this ).hide();
}
});
}
});

isHidden比较简单,接受2个参数,调用了jq的工具方法css来判断当前的display是否为none,为none返回真,否则走后面的contains方法
contains用于判断元素是否包含在元素所在的文档中,elem.ownerDocument其实就是document, elem是元素
由此可以看出,如果元素不包含在当前的文档中,jq也认为这个元素是隐藏的,比如document.createElement创建出来的元素。

function isHidden( elem, el ) {
elem = el || elem;
return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
}

showHide方法代码有点长,我们发现jQuery._data(),css_defaultDisplay(),curCSS(),这3个东西又是什么呢,稍后再分析。
showHide接受2个参数,elements : 元素集合 、 show : 布尔值(true表示显示 、false表示隐藏)

function showHide( elements, show ) {
var elem, display,
values = [],
index = 0,
length = elements.length; for ( ; index < length; index++ ) {
elem = elements[ index ];
if ( !elem.style ) {
continue;
}
values[ index ] = jQuery._data( elem, "olddisplay" );
if ( show ) {
// Reset the inline display of this element to learn if it is
// being hidden by cascaded rules or not
if ( !values[ index ] && elem.style.display === "none" ) {
elem.style.display = "";
} // Set elements which have been overridden with display: none
// in a stylesheet to whatever the default browser style is
// for such an element
if ( elem.style.display === "" && isHidden( elem ) ) {
values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
}
} else {
display = curCSS( elem, "display" ); if ( !values[ index ] && display !== "none" ) {
jQuery._data( elem, "olddisplay", display );
}
}
} // Set the display of most of the elements in a second loop
// to avoid the constant reflow
for ( index = 0; index < length; index++ ) {
elem = elements[ index ];
if ( !elem.style ) {
continue;
}
if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
elem.style.display = show ? values[ index ] || "" : "none";
}
} return elements;
}

我们先看代码最下面,它遍历了元素集合,如果元素没有样式则跳过,哪些元素没有样式呢,比如文本节点、注释节点等等。。。
我们特别注意一下这句代码:elem.style.display = show ? values[ index ] || "" : "none";
当为show时,它并没有直接写"block"而是一个变量赋值的操作,当它没有时才会空。
这里主要是为了区分元素的样式属性,比如span是行内元素如果给他赋blcok就变成块元素了,所以values[ index ]这个变量是在上面的代码处理过得到的。

for ( index = 0; index < length; index++ ) {
elem = elements[ index ];
if ( !elem.style ) {
continue;
}
if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
elem.style.display = show ? values[ index ] || "" : "none";
}
}

现在回过头看代码的开始部分就容易理解了,先获取元素默认的display值,一般第一次获取肯定是空的,因为这个值需要在隐藏时保存,我们看到下面就明白了,这里先不解释。

values[ index ] = jQuery._data( elem, "olddisplay" );

接着往下看,if(show)里面做了2个判断,第一个判断没什么说的,重点看第二个。
当行内样式为空,且是一个隐藏的元素(css样式表中display:none),则执行了一个比较有意思的操作。
利用css_defaultDisplay方法能够正确的获取到元素的样式属性,什么意思呢?
我们可以这样想,当一个元素初始的时候给一个display为none,我们肯定获取不到该元素显示时所对应的值,也就是说我们不知道是block,或是inline,换句话说,我们不知道该元素是块元素还是行内元素。
可是css_defaultDisplay方法能够做到,那么它是怎么实现的呢?

这里就不贴css_defaultDisplay的源码了,简单说一下它的原理,其实很简单
首先获取元素的nodeName(标签名) -> createElement动态的创建 -> 添加到document.body中 -> 获取该元素的display(元素默认的display都是显示,如div是block,span
是inline) -> 删除该元素

if ( show ) {
if ( !values[ index ] && elem.style.display === "none" ) {
elem.style.display = "";
} if ( elem.style.display === "" && isHidden( elem ) ) {
values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
}
} else {
......................
}

好了,if(show)里面的代码分析完了,我们再看分析一下else里面的代码
先获取display的值,再是一个判断,如果values[ index ]没有值并且display不是none,则把元素当前的display值保存起来,方便在if(show)中使用,就是上面提到的,不记得的话再去回顾一下。

if ( show ) {
.....................
} else {
display = curCSS( elem, "display" ); if ( !values[ index ] && display !== "none" ) {
jQuery._data( elem, "olddisplay", display );
}
}

最后分析一下toggle方法,其实也蛮简单的,遍历元素集合,判断bool是否为一个布尔值,是的话则判断state,state为真则调show方法,为假则调hide方法
如果bool不是布尔值,则判断该元素是否隐藏,隐藏的话则调show方法,显示的话则调hide方法

toggle: function( state, fn2 ) {
var bool = typeof state === "boolean"; ........................... return this.each(function() {
if ( bool ? state : isHidden( this ) ) {
jQuery( this ).show();
} else {
jQuery( this ).hide();
}
});
}

总结:

这3个方法最难的是show方法,先要获取values[ index ]保存的display默认值,如果它是空的,则需要调用css_defaultDisplay方法来变向的获取。
hide方法只是简单的dispaly=none,toggle只是根据state或者isHidden来调show方法或hide方法。

jquery的show/hide/toggle详解的更多相关文章

  1. jquery之hide()用法详解

    注:  以下函数用法和hide()类似  [参数类型完全一样] toggle() hide() show() slideToggle() slideUp() slideDown() fadeToggl ...

  2. jquery $.trim()去除字符串空格详解

    jquery $.trim()去除字符串空格详解 语法 jQuery.trim()函数用于去除字符串两端的空白字符. 作用 该函数可以去除字符串开始和末尾两端的空白字符(直到遇到第一个非空白字符串为止 ...

  3. jQuery基础入门+购物车案例详解

    jQuery是一个快速.简洁的JavaScript代码库(或JavaScript框架).jQuery设计的宗旨是"write Less,Do More",即倡导写更少的代码,做更多 ...

  4. jquery中的ajax方法详解

    定义和用法ajax() 方法通过 HTTP 请求加载远程数据.该方法是 jQuery 底层 AJAX 实现.简单易用的高层实现见 $.get, $.post 等.$.ajax() 返回其创建的 XML ...

  5. 【Jquery系列】JqGrid参数详解

    1   概述 本篇文章主要与大家分享JqGrid插件参数问题. 2   参数详解 2.1 初始化参数 2.2  ColModel参数 3   json数据 jqGrid可支持的数据类型:xml.jso ...

  6. 论如何把JS踩在脚下 —— JQuery基础及Ajax请求详解

    一.什么是JQuery? JQuery是一种JavaScript框架,是一堆大神搞出来的能够让前端程序猿敲更少代码.实现更多功能的工具(在此,跪谢各位JQuery开发大大们!!!).JQuery的使用 ...

  7. jQuery源码分析-构造函数详解

    在jQuery.js的构造函数中,充分利用了JavsScript语言的动态性——对行参的类型和个数没有的严格要求,以至于一个函数可以实现多种功能需求,也为JavaScript语言的多态性提供了基础,在 ...

  8. 生死相依:说说JQuery中die()、live()详解[翻译]

    一个web前端工程师,应该知道jquery的.live()函数,知道它是做什么用的,但是不知它是怎么样工作的,使用起来也是不得得心应手的,甚至也没听说过.die()(去掉bind事件).即使你能熟悉这 ...

  9. JQuery 源码解析 · extend()详解

    前言:最近想重写一个dropdown插件,于是想到了使用jquey实现插件,于是重温了一波$.extend()的知识,然后总结了这篇笔记 正文: $.extend(src)  jQuery.exten ...

随机推荐

  1. GTD工具 Wunderlist使用心得总结

    前言: 先后使用过do.it.omnifocus,最后选择了wunderlist,看了他拓展性强.跨平台.免费三大优点.Wunderlist只是一个工具,重要是的GTD的思路.下面的分享是本人的使用案 ...

  2. Spring(二)__bean的装配

    Bean的装配: 在spring容器内拼凑bean叫做装配.装 配bean的时候,需要告诉容器哪些bean 以及容器如何使用依赖注入将它们配合在一起. 上下文定义文件的根元素是<beans> ...

  3. 关于移动端meta设置

    <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initi ...

  4. 走进 .Net 单元测试

    走进 .Net 单元测试 Intro "不会写单元测试的程序员不是合格的程序员,不写单元测试的程序员不是优秀程序员." -- 一只想要成为一个优秀程序员的渣逼程序猿. 那么问题来了 ...

  5. SharePoint项目实践中如何实现非打破继承看上去很美的权限控制

    首先对于比较机密的数据,打破继承还是必须要的. 但是对于一些普通申请单据,虽然客户也希望用户不要看到其他人的申请单据,但是我还是不推荐打破继承,应为打破继承一方面会造成网站的权限管理特别的凌乱,另一方 ...

  6. Android 6.0 权限管理最佳实践

    博客: Android 6.0 运行时权限管理最佳实践 github: https://github.com/yanzhenjie/AndPermission

  7. IOS开发基础知识--碎片45

    1:iOS SEL的简单总结 SEL就是对方法的一种包装.包装的SEL类型数据它对应相应的方法地址,找到方法地址就可以调用方法 a.方法的存储位置 在内存中每个类的方法都存储在类对象中 每个方法都有一 ...

  8. 基于Ruby的Watir-WebDriver自动化测试方案

    Watir-WebDriver       —— 软件测试的自动化时代 QQ群:160409929 自动化测试方案书 系统架构 该自动化测试框架分三个模块:Test用例.Control控制层.Tool ...

  9. Jsoup解析html终于成功了!!!

    package com.eric.pickupjoke.activity; import java.io.IOException; import java.io.InputStream; import ...

  10. SQL Server 2012 安装图解教程

    在安装微软最新数据库SQL Server 2012之前,编者先确定一下安装环境:Windonws 7 SP1,32位操作系统.CPU是2.1GHz赛扬双核T3500,内存2.93GB 安装SQL Se ...