zoukankan      html  css  js  c++  java
  • 显示层封装及实现与优化(无动画+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

    原型对象上新增方法,可以增加多个方法

     必须直接调用,前面不能有元素 $.方法名()

     合并对象功能,如果对象有相同的属性,则后面的会覆盖前面的


  • 相关阅读:
    SQL------Hint
    JVM——垃圾回收
    JVM——内存结构
    SpringMVC——拦截器,过滤器实现登录拦截
    SpringMVC——参数传递
    SpringMVC——数据乱码问题
    SpringMVC——MVC执行流程底层剖析
    Spring——5种增强方式
    Spring——bean的五种作用域和生命周期
    Spring——多种方式实现依赖注入
  • 原文地址:https://www.cnblogs.com/chenyingying0/p/12343787.html
Copyright © 2011-2022 走看看