本篇文章一起了解一下jquery中show与链式调用的相关知识。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
jquery使用许久了,但是有一些api的实现实在想不通。下面将使用简化的代码来介绍,主要关注jquery的实现思想。
(function(window, undefined){function jquery(sel){return new jquery.prototype.init(sel);}jquery.prototype = {constructor: jquery,init: function(sel){if(typeof sel === 'string'){var that = this;var nodelist = document.queryselectorall(sel);array.prototype.foreach.call(nodelist, function(val, i){that[i] = val;})this.selector = sel;this.length = nodelist.length;}},show: function(){array.prototype.foreach.call(this, function(node){//if(node.style) continue; //textnode没有style//删除style上的display:nonevar display = node.style.display;if(display === 'none'){//dispaly置为空后,css如果有display则css的生效//否则默认的生效node.style.display = '';}//元素display值为非默认值情况,需要还原为olddisplay:div->display:inline-block//或 检测css上的display是否为noneif(node.style.display==='' || ishidden(node)){//有olddispaly则设置if(node.olddisplay) node.style.display = node.olddisplay;//没有则设置为元素默认值或元素当前值else node.style.display = getdisplay(node);}})//链式调用return this;},hide: function(){array.prototype.foreach.call(this, function(node){if(!ishidden(node)) {//jquery使用其cache机制存储信息,这里简化一下//直接挂载在对应的dom下node.olddisplay = getdisplay(node);node.style.display = 'none';}})return this;}}function getdisplay(node){var display = window.getcomputedstyle(node, null).getpropertyvalue('display');if(display === 'none'){var dom = document.createelement(node.nodename);//插入到body中document.body.appendchild(dom);//即可获取到元素display的默认值var display = window.getcomputedstyle(dom, null).getpropertyvalue('display');document.body.removechild(dom);}return display;}function ishidden(node) {//忽略未append进document的元素这种隐藏情况:$('<div>block</div>')未appendreturn window.getcomputedstyle(node, null).getpropertyvalue('display') === 'none';}jquery.prototype.init.prototype = jquery.prototype;window.$ = jquery;})(window);
先拿hide函数热身一下。如上篇提到的,jquery会将获取到的nodelist处理成数组,所以一上来,我们用foreach处理数组里的每一个node节点。
接下来,我们只需要将每一个节点的style.display置为'none'即可隐藏。很简单,对吧?(⊙0⊙) 。olddisplay和return this先不管╰( ̄▽ ̄)╮
hide: function(){array.prototype.foreach.call(this, function(node){if(!ishidden(node)) {//jquery使用其cache机制存储信息,这里简化一下//直接挂载在对应的dom下node.olddisplay = getdisplay(node);node.style.display = 'none';}})return this;}
其中ishidden是判断该元素是否隐藏:已经隐藏的元素就没必要再去处理了,直接跳过
function ishidden(node) {//忽略未append进document的元素这种隐藏情况:$('<div>block</div>')未appendreturn window.getcomputedstyle(node, null).getpropertyvalue('display') === 'none';}
--------------------------
接下来,来个稍繁琐的show。先抛出一个问题来引发一系列问题:
hide某个元素只需要将display:none,那么show呢?
display:block不就行了吗?这样确实可以将元素显示出来。但是万一元素原来的值是display:inline呢?
那在hide处保存原来的值不就行了吗?就像以下的代码:
node.olddisplay = getdisplay(node);
要是执行show前没有不执行hide呢?比如下面这种情况,不就没有olddisplay了吗(⊙0⊙)
<style>div{ display:none; }</style><div>display:none</div>$('div').show()
好,关键的地方到了:我们获取元素display的默认值就可以了吧?比如p默认是block,span默认是inline。
思路有了,那么接下来的问题是:如何获取元素display的默认值?
嘿嘿嘿,想不到吧?这里需要用点小技巧,大体思路如下:通过nodename创建一个新的标签,再获取。
有个地方可以再优化一下,getdisplay获取到元素display默认值后,可以使用jquery的cache机制存起来(实际上jquery也是这么做了)。
function getdisplay(node){var display = window.getcomputedstyle(node, null).getpropertyvalue('display');if(display === 'none'){var dom = document.createelement(node.nodename);//插入到body中document.body.appendchild(dom);//即可获取到元素display的默认值var display = window.getcomputedstyle(dom, null).getpropertyvalue('display');document.body.removechild(dom);}return display;}
然后,综合这两种情况:
//有olddispaly则设置if(node.olddisplay) node.style.display = node.olddisplay;//没有则设置为元素默认值或元素当前值else node.style.display = getdisplay(node);
以为这样就结束了?no,show函数的情况还是挺复杂的,我们大致要应对这几种情况:
<style>#none,#none2{ display: none; }</style><body><div id="div">默认值为block</div><span id="span">默认值为inline</span><div id="div2" style="display:inline-block;">修改为inline-block</div><div id="none">通过css隐藏了</div><div id="none2" style="display:none">通过css和style隐藏了</div></body>
最终,show函数变成了这鬼样ψ(╰_╯)。大致思路如下:
show: function(){array.prototype.foreach.call(this, function(node){//if(node.style) continue; //textnode没有style//删除style上的display:nonevar display = node.style.display;if(display === 'none'){//dispaly置为空后,css如果有display则css的生效//否则默认的生效node.style.display = '';}//元素display值为非默认值情况,需要还原为olddisplay:div->display:inline-block//或 检测css上的display是否为noneif(node.style.display==='' || ishidden(node)){//有olddispaly则设置if(node.olddisplay) node.style.display = node.olddisplay;//没有则设置为元素默认值或当前值else node.style.display = getdisplay(node);}})}
--------------------------
链式调用就是类似这种情况:
$('div').show().hide().css('height','300px').toggle()
实现起来非常简单,只要在每个函数后面return this即可
--------------------------
有同学说:喂!这个show,hide不对吧?是不是漏了时间参数? 用settimeout自己实现吧~>_<~+。
本节最主要是让大家知道jquery需要考虑的情况非常多(很多脏活)。即时简化了代码,依然还是这么长。
写完后,发现show还有一种情况没考虑:
div{ display:none !important; }<div>大家自己开脑洞,怎么处理吧(⊙0⊙)</div>
相关视频教程推荐:jquery教程(视频)