博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jquery的show/hide/toggle详解
阅读量:6078 次
发布时间:2019-06-20

本文共 5250 字,大约阅读时间需要 17 分钟。

通过阅读源码我们发现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方法。

转载于:https://www.cnblogs.com/gongshunkai/p/5930198.html

你可能感兴趣的文章
从头认识java-13.11 对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题?...
查看>>
Python-MacOSX下SIP引起的pip权限问题解决方案(非取消SIP机制)
查看>>
从MFQ方法到需求分析
查看>>
android.view.WindowManager$BadTokenException: Unable to add window
查看>>
HDU5012:Dice(bfs模板)
查看>>
iphone openssh
查看>>
Linux下MEncoder的编译
查看>>
Javascript中闭包(Closure)的探索(一)-基本概念
查看>>
spark高级排序彻底解秘
查看>>
ylbtech-LanguageSamples-PartialTypes(部分类型)
查看>>
福建省促进大数据发展:变分散式管理为统筹集中式管理
查看>>
开发环境、生产环境、测试环境的基本理解和区别
查看>>
tomcat多应用之间如何共享jar
查看>>
Flex前后台交互,service层调用后台服务的简单封装
查看>>
MySQL入门12-数据类型
查看>>
Windows Azure 保留已存在的虚拟网络外网IP(云服务)
查看>>
修改字符集
查看>>
HackTheGame 攻略 - 第四关
查看>>
js删除数组元素
查看>>
带空格文件名的处理(find xargs grep ..etc)
查看>>