showhide.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ width:360px; height:260px; background-color:pink; padding:20px; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box"></div> <script src="../js/jquery.js"></script> <script> var silent={ show:function($elem,showCall,shownCall){ if(typeof showCall === "function") showCall(); $elem.show(); if(typeof shownCall === "function") shownCall(); }, hide:function($elem,hideCall,hiddenCall){ if(typeof showCall === "function") hideCall(); $elem.hide(); if(typeof shownCall === "function") hiddenCall(); } } var css3={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var js={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var box=$(".box"); var btnShow=$("#btn-show"); var btnHide=$("#btn-hide"); btnShow.on("click",function(){ silent.show(box,function(){ box.html("我要顯示啦"); },function(){ setTimeout(function(){ box.html(box.html()+" 我已經顯示啦"); },1000) }); }); btnHide.on("click",function(){ silent.hide(box,function(){ },function(){ }); }); </script> </body> </html>
效果圖

這種方式有一個缺點,就是不適合多人協作的情況
因此選用發布訂閱的方式,使用 jquery的 trigger 來觸發事件
實作多人協作互不干擾
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ width:360px; height:260px; background-color:pink; padding:20px; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box"></div> <script src="../js/jquery.js"></script> <script> var silent={ show:function($elem){ $elem.trigger("show"); $elem.show(); $elem.trigger("shown"); }, hide:function($elem){ $elem.trigger("hide"); $elem.hide(); $elem.trigger("hidden"); } } var css3={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var js={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var box=$(".box"); $("#btn-show").on("click",function(){ silent.show(box); }); $("#btn-hide").on("click",function(e){ silent.hide(box); }); // 模擬多人協作,A操作文本 box.on("show shown",function(e){ //console.log(e.type); if(e.type==="show"){ box.html("我要顯示了"); } if(e.type==="shown"){ setTimeout(function(){ box.html(box.html()+"我已經顯示了"); },1000); } }); // 模擬多人協作,B操作背景色 box.on("show shown",function(e){ if(e.type==="show"){ box.css("background-color","lightgreen"); } if(e.type==="shown"){ setTimeout(function(){ box.css("background-color","orange"); },1000); } }); </script> </body> </html>
效果圖



需要增加判斷機制,在已經顯示的情況下,點擊顯示不再觸發顯示事件,避免性能浪費
解決連續點擊多次觸發的情況
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ width:360px; height:260px; background-color:pink; padding:20px; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box"></div> <script src="../js/jquery.js"></script> <script> var silent={ show:function($elem){ // 顯示狀態下不再重復顯示 if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; // 通過設定data-status的屬性來判斷當前的狀態 $elem.data("status","show").trigger("show"); $elem.show(); $elem.data("status","shown").trigger("shown"); }, hide:function($elem){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); $elem.hide(); $elem.data("status","hidden").trigger("hidden"); } } var css3={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var js={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var box=$(".box"); $("#btn-show").on("click",function(){ silent.show(box); }); $("#btn-hide").on("click",function(e){ silent.hide(box); }); box.on("show shown",function(e){ //console.log(e.type); if(e.type==="show"){ box.html("我要顯示了"); } if(e.type==="shown"){ setTimeout(function(){ box.html(box.html()+"我已經顯示了"); },1000); } }); </script> </body> </html>
但由于初始時box并沒有設定data-status屬性,因此總能至少執行一次
因此需要引入初始化操作,根據元素的狀態添加初始的data-status屬性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ width:360px; height:260px; background-color:pink; padding:20px; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box"></div> <script src="../js/jquery.js"></script> <script> var silent={ init:function($elem){ // elem.is(":hidden")判斷元素是否處于隱藏狀態 if($elem.is(":hidden")){ $elem.data("status","hidden"); }else{ $elem.data("status","shown"); } }, show:function($elem){ // 顯示狀態下不再重復顯示 if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; // 通過設定data-status的屬性來判斷當前的狀態 $elem.data("status","show").trigger("show"); $elem.show(); $elem.data("status","shown").trigger("shown"); }, hide:function($elem){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); $elem.hide(); $elem.data("status","hidden").trigger("hidden"); } } var css3={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var js={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } var box=$(".box"); silent.init(box); $("#btn-show").on("click",function(){ silent.show(box); }); $("#btn-hide").on("click",function(e){ silent.hide(box); }); box.on("show shown",function(e){ //console.log(e.type); if(e.type==="show"){ box.html("我要顯示了"); } if(e.type==="shown"){ setTimeout(function(){ box.html(box.html()+"我已經顯示了"); },1000); } }); </script> </body> </html>
將封裝的方法獨立出去 showhide.js
上面這些是無影片效果的顯示隱藏
下面來嘗試css3影片效果的顯示隱藏
首先給元素添加 transition 過渡
css部分添加
.transition{ -webkit-transition:all .5s; -moz-transition:all .5s; -ms-transition:all .5s; -o-transition:all .5s; transition:all .5s; }
html部分加上transition類
<div class="box transition"></div>
showhide.js
// css3影片方式 var css3={ fade:{ init:function($elem){ // elem.is(":hidden")判斷元素是否處于隱藏狀態 if($elem.is(":hidden")){ $elem.data("status","hidden"); }else{ $elem.data("status","shown"); } }, show:function($elem){ // 顯示狀態下不再重復顯示 if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; // 通過設定data-status的屬性來判斷當前的狀態 $elem.data("status","show").trigger("show"); $elem.show(); $elem.data("status","shown").trigger("shown"); }, hide:function($elem){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); $elem.hide(); $elem.data("status","hidden").trigger("hidden"); } }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
呼叫時
<script src="https://www.cnblogs.com/chenyingying0/js/showhide.js"></script>
<script>
var box=$(".box");
silent.init(box);
$("#btn-show").on("click",function(){
css3.fade.show(box);
});
$("#btn-hide").on("click",function(e){
css3.fade.hide(box);
});
box.on("show shown",function(e){
//console.log(e.type);
if(e.type==="show"){
box.html("我要顯示了");
}
if(e.type==="shown"){
setTimeout(function(){
box.html(box.html()+"我已經顯示了");
},1000);
}
});
</script>
測驗發現依然沒有影片效果,這是因為元素設定的display:block或者display:none來顯隱時默認就是沒有影片的
有一種解決方法是:使用opacity來控制影片
缺點是當opacity設定為0時,元素依舊占位,并且可以回應事件
回應事件的問題可以用visibility來解決,占位的問題可以用absolute絕對定位來解決
showhide.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ position: absolute;/*解決占位問題*/ width:360px; height:260px; background-color:pink; padding:20px; } .transition{ -webkit-transition:all .5s; -moz-transition:all .5s; -ms-transition:all .5s; -o-transition:all .5s; transition:all .5s; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box transition"></div> <button class="btn">測驗占位問題</button> <script src="../js/jquery.js"></script> <script src="../js/showhide.js"></script> <script> var box=$(".box"); silent.init(box); $("#btn-show").on("click",function(){ css3.fade.show(box); }); $("#btn-hide").on("click",function(e){ css3.fade.hide(box); }); box.on("show shown",function(e){ //console.log(e.type); if(e.type==="show"){ box.html("我要顯示了"); } if(e.type==="shown"){ setTimeout(function(){ box.html(box.html()+"我已經顯示了"); },1000); } }); //測驗發現opacity為0時依然可以回應事件 box.on("click",function(){ alert("我還可以回應事件呢~"); }) </script> </body> </html>
showhide.js
// 無影片方式 var silent={ init:function($elem){ // elem.is(":hidden")判斷元素是否處于隱藏狀態 if($elem.is(":hidden")){ $elem.data("status","hidden"); }else{ $elem.data("status","shown"); } }, show:function($elem){ // 顯示狀態下不再重復顯示 if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; // 通過設定data-status的屬性來判斷當前的狀態 $elem.data("status","show").trigger("show"); $elem.show(); $elem.data("status","shown").trigger("shown"); }, hide:function($elem){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); $elem.hide(); $elem.data("status","hidden").trigger("hidden"); } } // css3影片方式 var css3={ fade:{ init:function($elem){ // elem.is(":hidden")判斷元素是否處于隱藏狀態 if($elem.is(":hidden")){ $elem.data("status","hidden"); }else{ $elem.data("status","shown"); } }, show:function($elem){ // 顯示狀態下不再重復顯示 if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; // 通過設定data-status的屬性來判斷當前的狀態 $elem.data("status","show").trigger("show"); $elem.css({ "opacity":1, "visibility":"visible" }); $elem.data("status","shown").trigger("shown"); }, hide:function($elem){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); $elem.css({ "opacity":0, "visibility":"hidden"//解決回應事件的問題 }); $elem.data("status","hidden").trigger("hidden"); } }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } // js影片方式 var js={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
效果圖


但這并不是理想的解決方式
下面的解決方式是將 display 與 show hide 結合使用
showhide.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ width:360px; height:260px; background-color:pink; padding:20px; } .transition{ -webkit-transition:all .5s; -moz-transition:all .5s; -ms-transition:all .5s; -o-transition:all .5s; transition:all .5s; } .fadeOut{ opacity: 0; visibility: hidden; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box transition"></div> <button class="btn">測驗占位問題</button> <script src="../js/jquery.js"></script> <script src="../js/showhide.js"></script> <script> var box=$(".box"); css3.fade.init(box); $("#btn-show").on("click",function(){ css3.fade.show(box); }); $("#btn-hide").on("click",function(e){ css3.fade.hide(box); }); box.on("show shown hide hidden",function(e){ //console.log(e.type); if(e.type==="show"){ console.log("show"); } if(e.type==="shown"){ console.log("shown"); } if(e.type==="hide"){ console.log("hide"); } if(e.type==="hidden"){ console.log("hidden"); } }); </script> </body> </html>
showhide.js
// css3影片方式 var css3={ fade:{ init:function($elem){ // elem.is(":hidden")判斷元素是否處于隱藏狀態 if($elem.is(":hidden")){ $elem.data("status","hidden"); }else{ $elem.data("status","shown"); } }, show:function($elem){ if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; $elem.data("status","show").trigger("show"); $elem.show(); // transitionend事件只需要添加一次,不需要每次都添加 // 因此使用one而不是on $elem.one("transitionend",function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) //利用延遲達到異步的效果 //在使用transition沒有達到影片效果時,可以嘗試將同步變為異步 setTimeout(function(){ $elem.removeClass("fadeOut"); },20); }, hide:function($elem){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); //transitionend是jquery判斷影片執行完畢狀態的事件 //在影片執行完畢后隱藏元素 $elem.one("transitionend",function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass("fadeOut"); } }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
以上代碼存在一個問題,就是當點擊完顯示立即點擊隱藏時,顯示的影片仍會持續,而不會立刻停止開始隱藏
因此需要在系結transitionend事件之前先取消系結之前的transitionend
// css3影片方式 var css3={ fade:{ init:function($elem){ $elem.addClass("transition"); // elem.is(":hidden")判斷元素是否處于隱藏狀態 if($elem.is(":hidden")){ $elem.data("status","hidden"); $elem.addClass("fadeOut"); }else{ $elem.data("status","shown"); } }, show:function($elem){ if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; $elem.data("status","show").trigger("show"); $elem.show(); // transitionend事件只需要添加一次,不需要每次都添加 // 因此使用one而不是on $elem.off("transitionend").one("transitionend",function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) //利用延遲達到異步的效果 //在使用transition沒有達到影片效果時,可以嘗試將同步變為異步 setTimeout(function(){ $elem.removeClass("fadeOut"); },20); }, hide:function($elem){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); //transitionend是jquery判斷影片執行完畢狀態的事件 //在影片執行完畢后隱藏元素 $elem.off("transitionend").one("transitionend",function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass("fadeOut"); } }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
由于css3方式和默認無影片方式存在大量的代碼冗余,因此將重復部分提取成公共的函式
以下是代碼瘦身后的結果:
showhide.js
// 公共init function init($elem,hiddenCall){ if($elem.is(":hidden")){ $elem.data("status","hidden"); if(typeof hiddenCall==="function") hiddenCall(); }else{ $elem.data("status","shown"); } } //公共show function show($elem,callback){ if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; $elem.data("status","show").trigger("show"); callback(); } // 公共hide function hide($elem,callback){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); callback(); } // 無影片方式 var silent={ init:init, show:function($elem){ show($elem,function(){ $elem.show(); $elem.data("status","shown").trigger("shown"); }); }, hide:function($elem){ hide($elem,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); } } // css3影片方式 var css3={ fade:{ init:function($elem){ $elem.addClass("transition"); init($elem,function(){ $elem.addClass("fadeOut"); }); }, show:function($elem){ show($elem,function(){ $elem.off("transitionend").one("transitionend",function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) $elem.show(); setTimeout(function(){ $elem.removeClass("fadeOut"); },20); }); }, hide:function($elem){ hide($elem,function(){ $elem.off("transitionend").one("transitionend",function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass("fadeOut"); }); } }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } // js影片方式 var js={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }

transitionend 存在兼容性問題,需要做兼容處理(IE9以下不支持)
創建一個transition.js
(function(){ //判斷transition屬性是否存在 //存在:空字串 //不存在:undefined //console.log(document.body.style.transition); var transitionName={ transition:"transitionend", mozTransition:"transitionend", webkitTransition:"webkitTransitionEnd", oTransition:"oTransitionEnd otransitionend" }; var transitionEnd=""; var isSupport=false; for(var name in transitionName){ if(document.body.style[name]!="undefined"){ //說明存在 transitionEnd=transitionName[name]; isSupport=true; break; } } //將區域變數作為一個全域變數的屬性 window.mt=window.mt || {};//如果存在則繼續存在,不存在則創建一個空物件 window.mt.transition=transitionEnd; window.mt.isSupport=isSupport; })();
在頁面中測驗
<script src="https://www.cnblogs.com/chenyingying0/js/jquery.js"></script>
<script src="https://www.cnblogs.com/chenyingying0/js/transition.js"></script>
<script src="https://www.cnblogs.com/chenyingying0/js/showhide.js"></script>
<script>
console.log(window.mt.transition);//transitionend
console.log(window.mt.isSupport);//true
</script>
showhide.js修改
var transition=window.mt.transition; // 公共init function init($elem,hiddenCall){ if($elem.is(":hidden")){ $elem.data("status","hidden"); if(typeof hiddenCall==="function") hiddenCall(); }else{ $elem.data("status","shown"); } } //公共show function show($elem,callback){ if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; $elem.data("status","show").trigger("show"); callback(); } // 公共hide function hide($elem,callback){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); callback(); } // 無影片方式 var silent={ init:init, show:function($elem){ show($elem,function(){ $elem.show(); $elem.data("status","shown").trigger("shown"); }); }, hide:function($elem){ hide($elem,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); } } // css3影片方式 var css3={ fade:{ init:function($elem){ $elem.addClass("transition"); init($elem,function(){ $elem.addClass("fadeOut"); }); }, show:function($elem){ show($elem,function(){ $elem.off(transition).one(transition,function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) $elem.show(); setTimeout(function(){ $elem.removeClass("fadeOut"); },20); }); }, hide:function($elem){ hide($elem,function(){ $elem.off(transition).one(transition,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass("fadeOut"); }); } }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } } // js影片方式 var js={ fade:{ }, slideUpDown:{ }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
css3實作上下滾動
首先在css里添加 收縮狀態的樣式
/*收縮樣式*/ .slideUpDownCollapse{ height:0 !important;/*避免因為優先級不夠而無法生效*/ }
showhide.js中添加代碼
// css3影片方式 var css3={ fade:{ init:function($elem){ $elem.addClass("transition"); init($elem,function(){ $elem.addClass("fadeOut"); }); }, show:function($elem){ show($elem,function(){ $elem.off(transition).one(transition,function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) $elem.show(); setTimeout(function(){ $elem.removeClass("fadeOut"); },20); }); }, hide:function($elem){ hide($elem,function(){ $elem.off(transition).one(transition,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass("fadeOut"); }); } }, slideUpDown:{ init:function($elem){ $elem.addClass("transition"); init($elem,function(){ $elem.addClass("slideUpDownCollapse"); }); }, show:function($elem){ show($elem,function(){ $elem.off(transition).one(transition,function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) $elem.show(); setTimeout(function(){ $elem.removeClass("slideUpDownCollapse"); },20); }); }, hide:function($elem){ hide($elem,function(){ $elem.off(transition).one(transition,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass("slideUpDownCollapse"); }); } }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
呼叫
<script src="https://www.cnblogs.com/chenyingying0/js/jquery.js"></script>
<script src="https://www.cnblogs.com/chenyingying0/js/transition.js"></script>
<script src="https://www.cnblogs.com/chenyingying0/js/showhide.js"></script>
<script>
//console.log(window.mt.transition);//transitionend
//console.log(window.mt.isSupport);//true
var box=$(".box");
css3.slideUpDown.init(box);
$("#btn-show").on("click",function(){
css3.slideUpDown.show(box);
});
$("#btn-hide").on("click",function(e){
css3.slideUpDown.hide(box);
});
box.on("show shown hide hidden",function(e){
//console.log(e.type);
if(e.type==="show"){
console.log("show");
}
if(e.type==="shown"){
console.log("shown");
}
if(e.type==="hide"){
console.log("hide");
}
if(e.type==="hidden"){
console.log("hidden");
}
});
</script>
這是依賴于修改元素的height來實作的,有可能元素自身沒有height,而是被padding-top和padding-bottom給撐開的,如:
.box{ width:400px; /*height:300px;*//*height撐開*/ padding:150px 0;/*padding撐開*/ background-color:pink; }
這是需要在收縮類中將padding也設定為0
/*收縮樣式*/ .slideUpDownCollapse{ height:0 !important;/*避免因為優先級不夠而無法生效*/ padding-top:0 !important; padding-bottom:0 !important; }
有時元素既沒有設定高度,也沒有設定padding,而是被元素的內容給撐開的
這種情況下需要在初始化中先獲取到元素被內容撐開后的高度,然后將元素高度設定為該高度
注意的是容器需要設定溢位隱藏
.box{ width:400px; /*height:300px;*//*height撐開*/ /*padding:150px 0;*//*padding撐開*/ background-color:pink; overflow:hidden;/*被內容撐開高度,需要設定溢位隱藏*/ }
showhide.js的初始化中添加:
init:function($elem){ $elem.height($elem.height());//獲取到元素被內容撐開的高度,動態設定高度 $elem.addClass("transition"); init($elem,function(){ $elem.addClass("slideUpDownCollapse"); }); },
可以發現在css3的不同方法中,也存在大量重復的代碼,因此需要再次進行代碼提取
提取css3的公共部分,在css3內部,命名可以使用 _ 開頭(下劃線開頭)
slideLeftRight:和slideUpDown類似,將height的相關操作改為width,將padding-top/padding-bottom的相關操作改為padding-left/padding-right
fadeSlideUpDown:和slideUpDown類似,添加fadeOut和slideUpDownCollapse兩個類
fadeSlideLeftRight:和slideLeftRight類似,添加fadeOut和slideLeftRightCollapse兩個類
至此,css3的所有影片樣式完成:
showhide.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ width:400px; /*height:300px;*//*height撐開*/ /*padding:150px 0;*//*padding撐開*/ background-color:pink; overflow:hidden;/*被內容撐開高度,需要設定溢位隱藏*/ } .transition{ -webkit-transition:all .5s; -moz-transition:all .5s; -ms-transition:all .5s; -o-transition:all .5s; transition:all .5s; } .fadeOut{ opacity: 0; visibility: hidden; } /*收縮樣式*/ .slideUpDownCollapse{ height:0 !important;/*避免因為優先級不夠而無法生效*/ padding-top:0 !important; padding-bottom:0 !important; } .slideLeftRightCollapse{ width:0 !important;/*避免因為優先級不夠而無法生效*/ padding-left:0 !important; padding-right:0 !important; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box"> 內容<br> 撐開<br> 高度<br> </div> <button class="btn">測驗占位問題</button> <script src="../js/jquery.js"></script> <script src="../js/transition.js"></script> <script src="../js/showhide.js"></script> <script> //console.log(window.mt.transition);//transitionend //console.log(window.mt.isSupport);//true var box=$(".box"); css3.fadeSlideLeftRight.init(box); $("#btn-show").on("click",function(){ css3.fadeSlideLeftRight.show(box); }); $("#btn-hide").on("click",function(e){ css3.fadeSlideLeftRight.hide(box); }); box.on("show shown hide hidden",function(e){ //console.log(e.type); if(e.type==="show"){ console.log("show"); } if(e.type==="shown"){ console.log("shown"); } if(e.type==="hide"){ console.log("hide"); } if(e.type==="hidden"){ console.log("hidden"); } }); </script> </body> </html>
showhide.js
// css3影片方式 var css3={ _init:function($elem,className){ $elem.addClass("transition"); init($elem,function(){ $elem.addClass(className); }); }, _show:function($elem,className){ $elem.off(transition).one(transition,function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) $elem.show(); setTimeout(function(){ $elem.removeClass(className); },20); }, _hide:function($elem,className){ $elem.off(transition).one(transition,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass(className); }, //淡入淡出 fade:{ init:function($elem){ css3._init($elem,"fadeOut"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut"); }); } }, //上下滑動 slideUpDown:{ init:function($elem){ $elem.height($elem.height());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"slideUpDownCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"slideUpDownCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"slideUpDownCollapse"); }); } }, //左右滑動 slideLeftRight:{ init:function($elem){ $elem.width($elem.width());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"slideLeftRightCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"slideLeftRightCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"slideLeftRightCollapse"); }); } }, //淡入淡出式上下滑動 fadeSlideUpDown:{ init:function($elem){ $elem.height($elem.height());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"fadeOut slideUpDownCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut slideUpDownCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut slideUpDownCollapse"); }); } }, //淡入淡出式左右滑動 fadeSlideLeftRight:{ init:function($elem){ $elem.width($elem.width());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"fadeOut slideLeftRightCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut slideLeftRightCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut slideLeftRightCollapse"); }); } } }

接下來是js影片部分
首先fadeIn(fn) fadeOut(fn) slideDown(fn) slideUp(fn) 是jquery封裝好的,直接拿來用就行
// js影片方式 var js={ fade:{ init:function($elem){ $elem.removeClass("transition"); //如果用js影片的元素設定了transition屬性,會造成影片錯亂 //需要確保元素沒有transition屬性 init($elem); }, show:function($elem){ show($elem,function(){ //jquery封裝好的fadeIn(fn) $elem.stop().fadeIn(function(){ $elem.data("status","shown").trigger("shown"); }); }); }, hide:function($elem){ hide($elem,function(){ //jquery封裝好的fadeOut(fn) $elem.stop().fadeOut(function(){ $elem.data("status","hidden").trigger("hidden"); }); }); } }, slideUpDown:{ init:function($elem){ $elem.removeClass("transition"); //如果用js影片的元素設定了transition屬性,會造成影片錯亂 //需要確保元素沒有transition屬性 init($elem); }, show:function($elem){ show($elem,function(){ //jquery封裝好的slideDown(fn) $elem.stop().slideDown(function(){ $elem.data("status","shown").trigger("shown"); }); }); }, hide:function($elem){ hide($elem,function(){ $elem.stop().slideUp(function(){ $elem.data("status","hidden").trigger("hidden"); }); }); } }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
按照國際慣例,寫到這里依舊是提取一下公共部分
// js影片方式 var js={ _init:function($elem){ $elem.removeClass("transition"); init($elem); }, _show:function($elem,mode){ show($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","shown").trigger("shown"); }); }); }, _hide:function($elem,mode){ hide($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","hidden").trigger("hidden"); }); }); }, fade:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"fadeIn"); }, hide:function($elem){ js._hide($elem,"fadeOut"); } }, slideUpDown:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"slideDown"); }, hide:function($elem){ js._hide($elem,"slideUp"); } }, slideLeftRight:{ }, fadeSlideUpDown:{ }, fadeSlideLeftRight:{ } }
slideLeftRight 沒有封裝好的jquery方法,因此需要自己寫
大致思路就是通過改變width padding-left padding-right來實作
slideLeftRight:{ init:function($elem){ //獲取元素最開始的樣式屬性 var styles={}; styles["width"]=$elem.css("width"); styles["padding-left"]=$elem.css("padding-left"); styles["padding-right"]=$elem.css("padding-right"); $elem.data("styles",styles);//如果不保存,則styles為區域,無法在其他函式中使用 $elem.removeClass("transition"); init($elem,function(){ $elem.css({ "width":0, "padding-left":0, "padding-right":0 }); }); }, show:function($elem){ show($elem,function(){ var styles=$elem.data("styles"); $elem.show(); //使用animate進行影片 $elem.stop().animate({ "width":styles["width"], "padding-left":styles["padding-left"], "padding-right":styles["padding-right"] },function(){//影片結束后的回呼 $elem.data("status","shown").trigger("shown"); }); }); }, hide:function($elem){ hide($elem,function(){ //使用animate進行影片 $elem.stop().animate({ "width":0, "padding-left":0, "padding-right":0 },function(){//影片結束后的回呼 $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); }); } },
fadeSlideUpDown 與slideLeftRight類似,只是把width padding-left padding-right 換成height padding-top padding-bottom,再加上opacity
slideLeftRight:{ init:function($elem){ //獲取元素最開始的樣式屬性 var styles={}; styles["width"]=$elem.css("width"); styles["padding-left"]=$elem.css("padding-left"); styles["padding-right"]=$elem.css("padding-right"); $elem.data("styles",styles);//如果不保存,則styles為區域,無法在其他函式中使用 $elem.removeClass("transition"); init($elem,function(){ $elem.css({ "width":0, "padding-left":0, "padding-right":0 }); }); }, show:function($elem){ show($elem,function(){ var styles=$elem.data("styles"); $elem.show(); //使用animate進行影片 $elem.stop().animate({ "width":styles["width"], "padding-left":styles["padding-left"], "padding-right":styles["padding-right"] },function(){//影片結束后的回呼 $elem.data("status","shown").trigger("shown"); }); }); }, hide:function($elem){ hide($elem,function(){ //使用animate進行影片 $elem.stop().animate({ "width":0, "padding-left":0, "padding-right":0 },function(){//影片結束后的回呼 $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); }); } }, fadeSlideUpDown:{ init:function($elem){ //獲取元素最開始的樣式屬性 var styles={}; styles["opacity"]=$elem.css("opacity"); styles["height"]=$elem.css("height"); styles["padding-top"]=$elem.css("padding-top"); styles["padding-bottom"]=$elem.css("padding-bottom"); $elem.data("styles",styles);//如果不保存,則styles為區域,無法在其他函式中使用 $elem.removeClass("transition"); init($elem,function(){ $elem.css({ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 }); }); }, show:function($elem){ show($elem,function(){ var styles=$elem.data("styles"); $elem.show(); //使用animate進行影片 $elem.stop().animate({ "opacity":styles["opacity"], "height":styles["height"], "padding-top":styles["padding-top"], "padding-bottom":styles["padding-bottom"] },function(){//影片結束后的回呼 $elem.data("status","shown").trigger("shown"); }); }); }, hide:function($elem){ hide($elem,function(){ //使用animate進行影片 $elem.stop().animate({ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 },function(){//影片結束后的回呼 $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); }); } },
按照國際慣例繼續提取公共部分
完成所有js影片部分
// js影片方式 var js={ _init:function($elem,callback){ $elem.removeClass("transition"); init($elem,callback); }, _show:function($elem,mode){ show($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","shown").trigger("shown"); }); }); }, _hide:function($elem,mode){ hide($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","hidden").trigger("hidden"); }); }); }, //自定義初始化公共部分 _customInit:function($elem,options){//options是一個物件,包含所有要改變的屬性 var styles={}; for(var o in options){ styles[o]=$elem.css(o); } $elem.data("styles",styles);//如果不保存,則styles為區域,無法在其他函式中使用 js._init($elem,function(){ $elem.css(options); }); }, _customShow:function($elem){ show($elem,function(){ var styles=$elem.data("styles"); $elem.show(); //使用animate進行影片 $elem.stop().animate(styles,function(){//影片結束后的回呼 $elem.data("status","shown").trigger("shown"); }); }); }, _customHide:function($elem,options){ hide($elem,function(){ $elem.stop().animate(options,function(){//影片結束后的回呼 $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); }); }, fade:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"fadeIn"); }, hide:function($elem){ js._hide($elem,"fadeOut"); } }, slideUpDown:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"slideDown"); }, hide:function($elem){ js._hide($elem,"slideUp"); } }, slideLeftRight:{ init:function($elem){ js._customInit($elem,{ "width":0, "padding-left":0, "padding-right":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "width":0, "padding-left":0, "padding-right":0 }); } }, fadeSlideUpDown:{ init:function($elem){ js._customInit($elem,{ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 }); } }, fadeSlideLeftRight:{ init:function($elem){ js._customInit($elem,{ "opacity":0, "width":0, "padding-left":0, "padding-right":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "opacity":0, "width":0, "padding-left":0, "padding-right":0 }); } } }
最后,需要將以上這些代碼封裝成一個模塊
封裝好的showhide.js
(function($){ var transition=window.mt.transition;//支持的transition屬性 var isSupport=window.mt.isSupport;//是否支持transition // 公共init function init($elem,hiddenCall){ if($elem.is(":hidden")){ $elem.data("status","hidden"); if(typeof hiddenCall==="function") hiddenCall(); }else{ $elem.data("status","shown"); } } //公共show function show($elem,callback){ if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; $elem.data("status","show").trigger("show"); callback(); } // 公共hide function hide($elem,callback){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); callback(); } // 無影片方式 var silent={ init:init, show:function($elem){ show($elem,function(){ $elem.show(); $elem.data("status","shown").trigger("shown"); }); }, hide:function($elem){ hide($elem,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); } } // css3影片方式 var css3={ _init:function($elem,className){ $elem.addClass("transition"); init($elem,function(){ $elem.addClass(className); }); }, _show:function($elem,className){ $elem.off(transition).one(transition,function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) $elem.show(); setTimeout(function(){ $elem.removeClass(className); },20); }, _hide:function($elem,className){ $elem.off(transition).one(transition,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass(className); }, //淡入淡出 fade:{ init:function($elem){ css3._init($elem,"fadeOut"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut"); }); } }, //上下滑動 slideUpDown:{ init:function($elem){ $elem.height($elem.height());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"slideUpDownCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"slideUpDownCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"slideUpDownCollapse"); }); } }, //左右滑動 slideLeftRight:{ init:function($elem){ $elem.width($elem.width());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"slideLeftRightCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"slideLeftRightCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"slideLeftRightCollapse"); }); } }, //淡入淡出式上下滑動 fadeSlideUpDown:{ init:function($elem){ $elem.height($elem.height());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"fadeOut slideUpDownCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut slideUpDownCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut slideUpDownCollapse"); }); } }, //淡入淡出式左右滑動 fadeSlideLeftRight:{ init:function($elem){ $elem.width($elem.width());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"fadeOut slideLeftRightCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut slideLeftRightCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut slideLeftRightCollapse"); }); } } } // js影片方式 var js={ _init:function($elem,callback){ $elem.removeClass("transition"); init($elem,callback); }, _show:function($elem,mode){ show($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","shown").trigger("shown"); }); }); }, _hide:function($elem,mode){ hide($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","hidden").trigger("hidden"); }); }); }, //自定義初始化公共部分 _customInit:function($elem,options){//options是一個物件,包含所有要改變的屬性 var styles={}; for(var o in options){ styles[o]=$elem.css(o); } $elem.data("styles",styles);//如果不保存,則styles為區域,無法在其他函式中使用 js._init($elem,function(){ $elem.css(options); }); }, _customShow:function($elem){ show($elem,function(){ var styles=$elem.data("styles"); $elem.show(); //使用animate進行影片 $elem.stop().animate(styles,function(){//影片結束后的回呼 $elem.data("status","shown").trigger("shown"); }); }); }, _customHide:function($elem,options){ hide($elem,function(){ $elem.stop().animate(options,function(){//影片結束后的回呼 $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); }); }, fade:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"fadeIn"); }, hide:function($elem){ js._hide($elem,"fadeOut"); } }, slideUpDown:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"slideDown"); }, hide:function($elem){ js._hide($elem,"slideUp"); } }, slideLeftRight:{ init:function($elem){ js._customInit($elem,{ "width":0, "padding-left":0, "padding-right":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "width":0, "padding-left":0, "padding-right":0 }); } }, fadeSlideUpDown:{ init:function($elem){ js._customInit($elem,{ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 }); } }, fadeSlideLeftRight:{ init:function($elem){ js._customInit($elem,{ "opacity":0, "width":0, "padding-left":0, "padding-right":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "opacity":0, "width":0, "padding-left":0, "padding-right":0 }); } } } //設定默認引數 var defaults={ css3:false, js:false, animation:"fade" }; //封裝一個函式 function showHide($elem,options){ //$.extend( target [, object1 ] [, objectN ] ) //如果只有一個引數,默認target是jquery物件,該方法用于為全域物件jQuery添加新的函式 //如果多個物件具有相同的屬性,則后者會覆寫前者的屬性值,用于合并物件 //此處,options引數會覆寫默認引數,合并后的引數會賦值給options物件 var options=$.extend({},defaults,options); var mode=null;if(options.css3 && isSupport){//css3影片 mode=css3[options.animation] || css3[defaults.animation];//容錯 }else if(options.js){//js影片 mode=js[options.animation] || js[defaults.animation]; }else{//無影片 mode=silent; } mode.init($elem); //將對應的方法作為函式回傳值 return { // $.proxy(函式,指向,引數) // 本來是用來改變函式內this指向,此處主要用來傳參 // show:$.proxy(mode.show,this,$elem), // hide:$.proxy(mode.hide,this,$elem) show:mode.show, hide:mode.hide }; } window.mt=window.mt||{}; window.mt.showHide=showHide;//將showHide函式暴露在全域 })(jQuery);
補充一下這里 $.extend() 用法
$.extend( target, [obj1], [objn]
如果只有一個引數,則默認target是jquery,該方法用于為jquery添加新的函式
如果有多個引數,用于物件的合并,如果多個物件有相同的屬性,則后面的會覆寫掉前面的
呼叫時:
<script>
var box=$(".box");
//這種傳參方式不夠優雅
//此處需要傳入box
var showHide=window.mt.showHide(box,{
css3:true,
animation:"fadeSlideUpDown"
});
$("#btn-show").on("click",function(){
showHide.show(box);//此處需要傳入box
});
$("#btn-hide").on("click",function(e){
showHide.hide(box);//此處需要傳入box
});
box.on("show shown hide hidden",function(e){
if(e.type==="show"){
console.log("show");
}
if(e.type==="shown"){
console.log("shown");
}
if(e.type==="hide"){
console.log("hide");
}
if(e.type==="hidden"){
console.log("hidden");
}
});
</script>
在以上代碼呼叫中可以發現,box需要三次傳入,比較繁瑣
如果只想要傳入一次,需要在showhide.js中做以下修改:
//將對應的方法作為函式回傳值 return { // show:mode.show, // hide:mode.hide // $.proxy(函式,指向,引數) // 本來是用來改變函式內this指向,此處主要用來傳參 show:$.proxy(mode.show,this,$elem), hide:$.proxy(mode.hide,this,$elem) };
這樣的話呼叫時只有一處需要傳入box
<script>
var box=$(".box");
//只有這里需要傳入box
var showHide=window.mt.showHide(box,{
css3:true,
animation:"fadeSlideUpDown"
});
$("#btn-show").on("click",function(){
showHide.show();//使用$.proxy傳參后,這里就不再需要傳入引數
});
$("#btn-hide").on("click",function(e){
showHide.hide();//使用$.proxy傳參后,這里就不再需要傳入引數
});
box.on("show shown hide hidden",function(e){
if(e.type==="show"){
console.log("show");
}
if(e.type==="shown"){
console.log("shown");
}
if(e.type==="hide"){
console.log("hide");
}
if(e.type==="hidden"){
console.log("hidden");
}
});
</script>
這里補充一下 $.proxy() 的用法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>proxy</title> </head> <body> <button>點擊我</button> <script src="../js/jquery.js"></script> <script> var obj={ oname:"cyy", otell:function(){ console.log(this.oname); } } obj.otell();//cyy this指向obj $("button").on("click",obj.otell);//點擊按鈕列印undefined // 原因:this指向呼叫函式的button元素,而button元素沒有oname屬性 $("button").on("click",$.proxy(obj.otell,obj));//cyy // 解決1:$.proxy(方法,this指向) $("button").on("click",$.proxy(obj,"otell"));//cyy //解決2:$.proxy(this指向,方法名) //解決1與解決2等價 </script> </body> </html>

參考上面解決1的寫法: $.proxy( 方法, this指向,[引數] )
第三個引數是方法的傳參,如果沒有引數可以不傳
一般來說$.proxy() 是用來改變this的指向,這里我們用來傳參,這樣在呼叫時就不需要重復傳參
不過呢,以上這種呼叫方式還是不夠優雅
最推薦的是使用jquery插件的方式呼叫,接下來改裝代碼
showhide.js
(function($){ var transition=window.mt.transition;//支持的transition屬性 var isSupport=window.mt.isSupport;//是否支持transition // 公共init function init($elem,hiddenCall){ if($elem.is(":hidden")){ $elem.data("status","hidden"); if(typeof hiddenCall==="function") hiddenCall(); }else{ $elem.data("status","shown"); } } //公共show function show($elem,callback){ if($elem.data("status")==="show") return; if($elem.data("status")==="shown") return; $elem.data("status","show").trigger("show"); callback(); } // 公共hide function hide($elem,callback){ if($elem.data("status")==="hide") return; if($elem.data("status")==="hidden") return; $elem.data("status","hide").trigger("hide"); callback(); } // 無影片方式 var silent={ init:init, show:function($elem){ show($elem,function(){ $elem.show(); $elem.data("status","shown").trigger("shown"); }); }, hide:function($elem){ hide($elem,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); } } // css3影片方式 var css3={ _init:function($elem,className){ $elem.addClass("transition"); init($elem,function(){ $elem.addClass(className); }); }, _show:function($elem,className){ $elem.off(transition).one(transition,function(){//影片執行完畢后執行shown $elem.data("status","shown").trigger("shown"); }) $elem.show(); setTimeout(function(){ $elem.removeClass(className); },20); }, _hide:function($elem,className){ $elem.off(transition).one(transition,function(){ $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }) $elem.addClass(className); }, //淡入淡出 fade:{ init:function($elem){ css3._init($elem,"fadeOut"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut"); }); } }, //上下滑動 slideUpDown:{ init:function($elem){ $elem.height($elem.height());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"slideUpDownCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"slideUpDownCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"slideUpDownCollapse"); }); } }, //左右滑動 slideLeftRight:{ init:function($elem){ $elem.width($elem.width());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"slideLeftRightCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"slideLeftRightCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"slideLeftRightCollapse"); }); } }, //淡入淡出式上下滑動 fadeSlideUpDown:{ init:function($elem){ $elem.height($elem.height());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"fadeOut slideUpDownCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut slideUpDownCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut slideUpDownCollapse"); }); } }, //淡入淡出式左右滑動 fadeSlideLeftRight:{ init:function($elem){ $elem.width($elem.width());//獲取到元素被內容撐開的高度,動態設定高度 css3._init($elem,"fadeOut slideLeftRightCollapse"); }, show:function($elem){ show($elem,function(){ css3._show($elem,"fadeOut slideLeftRightCollapse"); }); }, hide:function($elem){ hide($elem,function(){ css3._hide($elem,"fadeOut slideLeftRightCollapse"); }); } } } // js影片方式 var js={ _init:function($elem,callback){ $elem.removeClass("transition"); init($elem,callback); }, _show:function($elem,mode){ show($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","shown").trigger("shown"); }); }); }, _hide:function($elem,mode){ hide($elem,function(){ $elem.stop()[mode](function(){ $elem.data("status","hidden").trigger("hidden"); }); }); }, //自定義初始化公共部分 _customInit:function($elem,options){//options是一個物件,包含所有要改變的屬性 var styles={}; for(var o in options){ styles[o]=$elem.css(o); } $elem.data("styles",styles);//如果不保存,則styles為區域,無法在其他函式中使用 js._init($elem,function(){ $elem.css(options); }); }, _customShow:function($elem){ show($elem,function(){ var styles=$elem.data("styles"); $elem.show(); //使用animate進行影片 $elem.stop().animate(styles,function(){//影片結束后的回呼 $elem.data("status","shown").trigger("shown"); }); }); }, _customHide:function($elem,options){ hide($elem,function(){ $elem.stop().animate(options,function(){//影片結束后的回呼 $elem.hide(); $elem.data("status","hidden").trigger("hidden"); }); }); }, fade:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"fadeIn"); }, hide:function($elem){ js._hide($elem,"fadeOut"); } }, slideUpDown:{ init:function($elem){ js._init($elem); }, show:function($elem){ js._show($elem,"slideDown"); }, hide:function($elem){ js._hide($elem,"slideUp"); } }, slideLeftRight:{ init:function($elem){ js._customInit($elem,{ "width":0, "padding-left":0, "padding-right":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "width":0, "padding-left":0, "padding-right":0 }); } }, fadeSlideUpDown:{ init:function($elem){ js._customInit($elem,{ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "opacity":0, "height":0, "padding-top":0, "padding-bottom":0 }); } }, fadeSlideLeftRight:{ init:function($elem){ js._customInit($elem,{ "opacity":0, "width":0, "padding-left":0, "padding-right":0 }); }, show:function($elem){ js._customShow($elem); }, hide:function($elem){ js._customHide($elem,{ "opacity":0, "width":0, "padding-left":0, "padding-right":0 }); } } } //設定默認引數 var defaults={ css3:false, js:false, animation:"fade" }; //封裝一個函式 function showHide($elem,options){ var mode=null; if(options.css3 && isSupport){//css3影片 mode=css3[options.animation] || css3[defaults.animation];//容錯 }else if(options.js){//js影片 mode=js[options.animation] || js[defaults.animation]; }else{//無影片 mode=silent; } mode.init($elem); return { show:$.proxy(mode.show,this,$elem), hide:$.proxy(mode.hide,this,$elem) }; } // 改成jquery插件方式 $.fn.extend({ showHide:function(opt){ //this指向呼叫該插件的元素,這里是box //可能是一個元素,也可以是多個元素,因此使用each遍歷 return this.each(function(){ var ui=$(this); // 如果options傳遞的是引數物件,則options屬性與defaults屬性進行合并,存入空物件中賦值給options // 如果options傳遞的不是物件,則為false,屬性為defaults默認屬性,并賦值給options // $.extend(target, obj1, objn) 物件合并 var options=$.extend({},defaults,typeof opt==="object" && opt); /* opt為引數物件時,如: box.showHide({ css3:true, animation:"slideLeftRight" }); */ var mode=ui.data("showHide"); //mode物件實體只需要生成一次 if(!mode){ mode=showHide(ui,options);//mode回傳包含show和hide方法的一個物件 ui.data("showHide",mode); } /* opt為show或者hide字串時,如: box.showHide("show"); */ //如果options是show或者hide的字串,則執行方法 if(typeof mode[opt]==="function"){ mode[opt](); } }) } }); })(jQuery);
showhide.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>showhide</title> <link rel="stylesheet" href="../css/base.css"> <style> body{ width:400px; margin:0 auto; } button{ width:50%; height:30px; background: #abcdef; } .box{ width:400px; /*height:300px;*//*height撐開*/ /*padding:150px 0;*//*padding撐開*/ background-color:pink; overflow:hidden;/*被內容撐開高度,需要設定溢位隱藏*/ } .transition{ -webkit-transition:all .5s; -moz-transition:all .5s; -ms-transition:all .5s; -o-transition:all .5s; transition:all .5s; } .fadeOut{ opacity: 0; visibility: hidden; } /*收縮樣式*/ .slideUpDownCollapse{ height:0 !important;/*避免因為優先級不夠而無法生效*/ padding-top:0 !important; padding-bottom:0 !important; } .slideLeftRightCollapse{ width:0 !important;/*避免因為優先級不夠而無法生效*/ padding-left:0 !important; padding-right:0 !important; } </style> </head> <body> <button id="btn-show" class="btn">顯示</button><button id="btn-hide" class="btn">隱藏</button> <div class="box"> 內容<br> 撐開<br> 高度<br> </div> <button class="btn">測驗占位問題</button> <script src="../js/jquery.js"></script> <script src="../js/transition.js"></script> <script src="../js/showhide.js"></script> <script> var box=$(".box"); //jquery插件方式傳參 box.showHide({ css3:true, animation:"slideLeftRight" });//回傳一個包含show和hide方法的物件mode $("#btn-show").on("click",function(){ //jquery插件方式呼叫 box.showHide("show"); }); $("#btn-hide").on("click",function(e){ //jquery插件方式呼叫 box.showHide("hide"); }); box.on("show shown hide hidden",function(e){ if(e.type==="show"){ console.log("show"); } if(e.type==="shown"){ console.log("shown"); } if(e.type==="hide"){ console.log("hide"); } if(e.type==="hidden"){ console.log("hidden"); } }); </script> </body> </html>
最后效果圖

知識點補充:
trigger和triggerHandler的區別:
區別就是trigger會導致瀏覽器同名的默認行為的執行,如:
trigger('submit');不但會執行submit()函式的效果,也會執行表單提交的效果;
而triggerHandler就不會導致默認行為的執行,
另外,它們兩個很相似,如果能夠實作同樣的效果,使用哪一個都行
$.fn $.fn.extend $.extend 區別:
$.fn
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>fnExtend</title> <style> .box{ width:200px; height:200px; padding:20px; text-align:center; line-height: 200px; border:1px solid #333; margin:100px auto; } </style> </head> <body> <div class="box">我是box</div> <script src="../js/jquery.js"></script> <script> //$.fn 原型物件上新增方法,一次只能添加一個 $.fn.pink=function(){ $(this).css("background-color","pink"); }; $(".box").pink();//div背景變粉色 $.pink();//不可以直接呼叫 </script> </body> </html>

$.fn.extend
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>fnExtend</title> <style> .box{ width:200px; height:200px; padding:20px; text-align:center; line-height: 200px; border:1px solid #333; margin:100px auto; } </style> </head> <body> <div class="box">我是box</div> <script src="../js/jquery.js"></script> <script> //$.fn.extend 原型物件上新增方法,可以在增加多個方法 $.fn.extend({ pink:function(){ $(this).css("background-color","pink"); }, blue:function(){ $(this).css("background-color","#abcdef"); } }); $(".box").blue();//div背景變藍色 //$.blue();//不可以直接呼叫 // 合并物件功能,如果物件有相同的屬性,則后面的會覆寫前面的 var obj1={ a:1, b:2 }; var obj2={ b:3, c:4 }; $.fn.extend(obj1,obj2);//將obj2合并到obj1中 console.log(obj1);//{a: 1, b: 3, c: 4} var newObj=$.fn.extend({},obj1,obj2);//將obj2和obj1合并到空物件中,賦值給newObj console.log(newObj);//{a: 1, b: 3, c: 4} </script> </body> </html>

$.extend
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>fnExtend</title> <style> .box{ width:200px; height:200px; padding:20px; text-align:center; line-height: 200px; border:1px solid #333; margin:100px auto; } </style> </head> <body> <div class="box">我是box</div> <script src="../js/jquery.js"></script> <script> //$.extend新增方法 $.extend({ pink:function(){ console.log("pink"); }, blue:function(){ console.log("blue"); } }); $.blue();//blue 需要直接呼叫 $(".box").blue();//報錯 // 合并物件,功能與$.fn.extend相同 var obj1={ a:1, b:2 }; var obj2={ b:3, c:4 }; $.extend(obj1,obj2);//將obj2合并到obj1中 console.log(obj1);//{a: 1, b: 3, c: 4} </script> </body> </html>
總結:
$.fn
原型物件上新增方法,一次只能添加一個
不可以直接呼叫,需要有元素 elem.方法名()
$.fn.extend
原型物件上新增方法,可以增加多個方法
不可以直接呼叫,需要有元素 elem.方法名()
合并物件功能,如果物件有相同的屬性,則后面的會覆寫前面的
$.extend
原型物件上新增方法,可以增加多個方法
必須直接呼叫,前面不能有元素 $.方法名()
合并物件功能,如果物件有相同的屬性,則后面的會覆寫前面的
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/7136.html
標籤:jQuery
