jQuery의 쇼 및 체인 호출 관련 지식에 대한 간략한 토론

PHPz
풀어 주다: 2021-05-28 18:01:42
앞으로
3594명이 탐색했습니다.

이번 글에서는 jQuery의 show 및 chain call에 대해 알아보겠습니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.

jQuery의 쇼 및 체인 호출 관련 지식에 대한 간략한 토론

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: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的元素这种隐藏情况:$(&#39;<div>block</div>&#39;)未append
return window.getComputedStyle(node, null).getPropertyValue(&#39;display&#39;) === &#39;none&#39;;
}
jQuery.prototype.init.prototype = jQuery.prototype;
window.$ = jQuery;
})(window);
로그인 후 복사

먼저 숨기기 기능으로 몸을 풀어보세요. 이전 글에서 언급했듯이 jQuery는 획득한 nodeList를 배열로 처리하므로 먼저 forEach를 사용하여 배열의 각 노드를 처리합니다.

다음으로, 숨기려면 각 노드의 style.display를 'none'으로 설정하면 됩니다. 아주 간단하죠? ( ⊙0 ) . oldDisplay를 무시하고 지금은 이것을 반환하세요╰( ̄▽ ̄)╮

hide: function(){
Array.prototype.forEach.call(this, function(node){
if(!isHidden(node)) {
//jQuery使用其cache机制存储信息,这里简化一下
//直接挂载在对应的dom下
node.oldDisplay = getDisplay(node);
node.style.display = &#39;none&#39;;
}
})
return this;
}
로그인 후 복사

여기서 isHidden은 요소가 숨겨져 있는지 확인하는 데 사용됩니다. 이미 숨겨진 요소를 처리할 필요가 없습니다. <를 건너뛰기만 하면 됩니다. 🎜>

function isHidden(node) {
//忽略未append进document的元素这种隐藏情况:$(&#39;<div>block</div>&#39;)未append
return window.getComputedStyle(node, null).getPropertyValue(&#39;display&#39;) === &#39;none&#39;;
}
로그인 후 복사
---------------


다음은 조금 번거롭지만 보여주다. 먼저 일련의 질문을 촉발하는 질문을 제기하세요.


특정 요소 숨기기에는 표시만 필요합니다:없음, 하지만 표시는 어떻습니까?


디스플레이:차단만으로는 충분하지 않나요? 그러면 실제로 요소가 표시됩니다. 하지만 요소의 원래 값이 display:inline이면 어떻게 될까요?


hide에 원래 값을 저장하면 충분하지 않을까요? 다음 코드와 같습니다.

node.oldDisplay = getDisplay(node);
로그인 후 복사
show가 실행되기 전에 hide가 실행되지 않으면 어떻게 되나요? 예를 들어, 다음과 같은 상황에서는 oldDisplay가 없지 않을까요? (⊙0⊙)

<style>
div{ display:none; }
</style>
<div>display:none</div>$(&#39;div&#39;).show()
로그인 후 복사
알겠습니다. 여기서 중요한 점은 요소 표시의 기본값만 가져오면 된다는 것입니다. 오른쪽? 예를 들어 p의 기본값은 block이고,span의 기본값은 inline입니다.


이제 아이디어가 생겼으니 다음 질문은

요소 표시의 기본값을 얻는 방법입니다.

헤헤헤헤 생각이 나지 않나요? 여기에는 약간의 트릭이 필요합니다. 일반적인 아이디어는 다음과 같습니다. nodeName을 통해 새 레이블을 만든 다음 가져옵니다.


더 최적화할 수 있는 곳이 있습니다. getDisplay가 요소의 기본 표시 값을 얻은 후 jQuery의 캐시 메커니즘을 사용하여 저장할 수 있습니다(실제로 jQuery도 이 작업을 수행합니다).

function getDisplay(node){
var display = window.getComputedStyle(node, null).getPropertyValue(&#39;display&#39;);
if(display === &#39;none&#39;){
var dom = document.createElement(node.nodeName);
//插入到body中
document.body.appendChild(dom);
//即可获取到元素display的默认值
var display = window.getComputedStyle(dom, null).getPropertyValue(&#39;display&#39;);
document.body.removeChild(dom);
}
return display;
}
로그인 후 복사
그럼 이 두 가지 상황을 합치면

//有oldDispaly则设置
if(node.oldDisplay) node.style.display = node.oldDisplay;
//没有则设置为元素默认值或元素当前值
else node.style.display = getDisplay(node);
로그인 후 복사
이것이 끝이라고 생각하시나요? 아니요, 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 함수는 이런 이상한 ψ(╰_╯)로 변했습니다. 일반적인 아이디어는 다음과 같습니다.


jQuery의 쇼 및 체인 호출 관련 지식에 대한 간략한 토론

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 === &#39;none&#39;){
//dispaly置为空后,css如果有display则css的生效
//否则默认的生效
node.style.display = &#39;&#39;;
}
//元素display值为非默认值情况,需要还原为oldDisplay:div->display:inline-block
//或 检测css上的display是否为none
if(node.style.display===&#39;&#39; || isHidden(node)){
//有oldDispaly则设置
if(node.oldDisplay) node.style.display = node.oldDisplay;
//没有则设置为元素默认值或当前值
else node.style.display = getDisplay(node);
}
})
}
로그인 후 복사
---------------------- -- -


Chain call은 이 상황과 유사합니다.

$(&#39;div&#39;).show().hide().css(&#39;height&#39;,&#39;300px&#39;).toggle()
로그인 후 복사
은 구현이 매우 간단합니다. 각 함수는 나중에 반환하세요


---------------


예 동급생이 말했습니다: 안녕하세요! 이거 쇼앤하이드 맞죠? 시간 매개변수를 놓쳤나요? setTimeOut을 이용해 직접 구현해 보세요~>_<~+.


이 섹션의 주요 목적은 jQuery가 고려해야 할 많은 상황(많은 지저분한 작업)이 있다는 것을 모두에게 알리는 것입니다. 코드를 단순화해도 여전히 너무 깁니다.


글을 다 쓴 후, 쇼가 고려하지 않은 또 다른 상황이 있다는 것을 발견했습니다:

div{ display:none !important; }
<div>大家自己开脑洞,怎么处理吧(⊙0⊙)</div>
로그인 후 복사
추천 관련 비디오 튜토리얼:

jQuery Tutorial (비디오 )

관련 라벨:
원천:jb51.net
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿