显示层封装及实现与优化(无动画+css3动画+js动画)
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="../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="../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
</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="../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.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
原型对象上新增方法,可以增加多个方法
必须直接调用,前面不能有元素 $.方法名()
合并对象功能,如果对象有相同的属性,则后面的会覆盖前面的
显示层封装及实现与优化(无动画+css3动画+js动画)的更多相关文章
- 前端优化之动画为什么要尽量用css3代替js
导致JavaScript效率低的两大原因:操作DOM和使用页面动画.通常我们会通过频繁的操作 DOM的CSS来实现视觉上的动画效果,导致js效率低的两个因素都包括在内了在频繁的操作DOM和CSS时,浏 ...
- 系统管理模块_部门管理_改进_抽取添加与修改JSP页面中的公共代码_在显示层抽取BaseAction_合并Service层与Dao层
系统管理模块_部门管理_改进1:抽取添加与修改JSP页面中的公共代码 commons.jspf <%@ page language="java" import="j ...
- Django drf:视图层封装、ViewSetMixin、路由配置、解析器、响应器
一.视图层封装 二.ViewSetMixin 三.路由配置 四.解析器 五.响应器 一.视图层封装 1.基本视图 写一个出版社的增删改查resfull接口 路由: url(r'^publish/$', ...
- 使用jquery封装的动画脚本(无动画、css3动画、js动画)
自己封装好的showhide.js 包含无动画.css3动画.js动画 包括:fade(淡入淡出) slideUpDown(上下滑动) slideLeftRight(左右滑动) fadeSlid ...
- 无阻塞加载js,防止因js加载不了影响页面显示
浏览器加载静态资源和js的方式都是线性加载,所以一般情况可以将js放到</body>前,防止UI线程的阻塞. 而某些时候我们既希望js在整个网页的头部就加载,又担心js阻塞导致网站加载缓慢 ...
- Android上的MVP:如何组织显示层的内容
MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一个演化版本,目前它在Android应用开发中越来越重要了,大家也都在讨论关于M ...
- SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装
SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装 >>>>>>>& ...
- Jquery实现鼠标移到某个对象,弹出显示层。
/** * 鼠标移上去显示层 * @param divId 显示的层ID * @returns */ $.fn.myHoverTip = function(divId) { var div = $(& ...
- 小程序api请求层封装(Loading全局配置)
前言 小程序开发,没有vue中的axios那么好使,请求层的封装需要自己来搞. 当然请求层的配置少不了loading,这里索性也就将loading做一个配置,避免以后重复造轮子 请求封装 小程序中有封 ...
随机推荐
- python接口测试,mock模块基本使用介绍
mock简介 py3已将mock集成到unittest库中 为的就是更好的进行单元测试 简单理解,模拟接口返回参数 通俗易懂,直接修改接口返回参数的值 mock作用 解决依赖问题,达到解耦作用 当我们 ...
- [bzoj3925] [洛谷P3343] [ZJOI2015] 地震后的幻想乡
Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任 ...
- [洛谷P3621] [APIO2007] 风铃
Description 你准备给弟弟 Ike 买一件礼物,但是,Ike 挑选礼物的方式很特别:他只喜欢那些能被他排成有序形状的东西. 你准备给 Ike 买一个风铃.风铃是一种多层的装饰品,一般挂在天花 ...
- 【转】在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解)
原文:http://www.cyqdata.com/cnblogs/article-detail-35876# 背景 在项目过程中,有时候你需要调用非C#编写的DLL文件,尤其在使用一些第三方通讯组件 ...
- 远程桌面软件RDCMan汉化版
自己汉化的远程桌面控制软件RDCMan--Remote Desktop Connection Manager(RDCMan) v2.7 简体中文汉化版. 介绍 Remote Desktop Conne ...
- (初学JS)JS基础——ATM机终端程序编写<1.0>
初步学习了JS基础,为了更好地将所学知识熟练运用,我进行了银行ATM存取款机的模拟程序编写,主要通过VScode终端实现系列操作. 我的ATM程序包括6个主要功能:1.查询余额 2.存钱 3. 取钱 ...
- Centos 7 最小化部署svn版本控制(svn协议)
1.关闭selinux sh-4.2# sed -i 's/enforcing/disabled/' /etc/selinux/config sh-4.2# reboot 2.卸载防火墙 sh-4.2 ...
- 使用Gradle构建springboot多模块项目,并混合groovy开发
idea设置本地gradle 打包: build.gradle //声明gradle脚本自身需要使用的资源,优先执行 buildscript { ext { springBootVersion = ' ...
- django用户认证的session的应用
from django.shortcuts import render,redirect def login(request): if request.method=='GET': return re ...
- 人生需要Plan B
天有不测风云,人有祸兮旦福.2020年,刚打开就是地狱模式! 武汉加油,中国加油! 新冠状肺炎的强传播性,让人们不得不乖乖待在家,工地开不了工,白领不能上班,农村封村,城市封小区.人们每天在一个小范围 ...