jQuery链式调用与show知识浅析
来源: 阅读:672 次 日期:2016-07-01 14:24:23
温馨提示: 小编为您整理了“jQuery链式调用与show知识浅析”,方便广大网友查阅!

这篇文章主要介绍了jQuery的XX如何实现?——2.show与链式调用 的相关资料,非常具有参考借鉴价值,感兴趣的朋友一起学习吧

jQuery使用许久了,但是有一些API的实现实在想不通。下面将使用简化的代码来介绍,主要关注jQuery的实现思想。

相较于上一篇,代码更新了:21~78

(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:none

var display = node.style.display;

if(display === 'none'){

//dispaly置为空后,css如果有display则css的生效

//否则默认的生效

node.style.display = '';

}

//元素display值为非默认值情况,需要还原为oldDisplay:div->display:inline-block

//或 检测css上的display是否为none

if(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>')未append

return 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>')未append

return 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的默认值就可以了吧?比如div默认是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:none

var display = node.style.display;

if(display === 'none'){

//dispaly置为空后,css如果有display则css的生效

//否则默认的生效

node.style.display = '';

}

//元素display值为非默认值情况,需要还原为oldDisplay:div->display:inline-block

//或 检测css上的display是否为none

if(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>

更多信息请查看网络编程
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:hfpxwx
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map