Jquery的slideDown、slideUp、slideToggle原理

话不多说,先上全部代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #dom_id{
            width: 100px;
            background-color: #e0e0e0;
            font-size: 12px;
            text-align: center;
        }
        .btn{
            width: 70px;
            height: 35px;
            line-height: 35px;
            text-align: center;
            font-size: 14px;
            background-color: #9c9c9c;
            user-select: none;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div id="dom_id" >
        <div>something dangerous</div>
        <!-- <div>丝滑</div> -->
        <div>丝滑</div>
    </div>
    <div class="btn" data-status="show" onclick="slideToogle(event,'dom_id',500)">切换</div>
<script>
    function slideToogle(e,el,duration=1000){
        var dom = document.getElementById(el)
        var status = e.target.dataset.status
        var flag = e.target.dataset.status == 'show' //保存当前的状态,方便进行判断
        e.target.dataset.status = flag?'hide':'show' //如果本来是show,现在就更改为隐藏,懒省事的写法
        dom.style.transition = 'height '+duration/1000+'s' //设置动画时间
        dom.style.overflow = 'hidden'     //保证子元素不外溢
        animateDom(flag,dom,duration)     //操作dom的height属性
    }

    function animateDom(flag,dom,duration){    
        clearTimeout(dom.tagTimer);
        setData(dom);
        dom.style.height = flag?dom.tagHeight:"0px"
        setTimeout(()=>{
            dom.style.height = flag?"0px":dom.tagHeight
        },0)
        dom.tagTimer = setTimeout(()=>{
            dom.style.display = flag?'none':'block'
            dom.style.transition = '';
            dom.style.overflow = '';
            dom.style.height = '';
        },duration)
    }

    function setData(dom){
        dom.tagTimer = dom.tagTimer || null
        dom.style.display = 'block';
        dom.tagHeight = dom.tagHeight || dom.clientHeight+'px'
        dom.style.display = '';
    }
        
</script>
</body>
</html>

Transtion属性

jquery、及vue的slide效果都用到了transition属性,这个属性设置的是元素的过渡效果,想要有这种丝滑的动态效果,必须要设置该属性

div{
    height: 50px;
    /* 下面这行表示,height值如果变化,就会在1秒内线性变化到指定的值 */
    transition: height 1s linear;
}

对要操作的dom进行处理

我在dom加了一个属性data-status为了方便控制显示和隐藏(其实可以直接设置在js的dom对象上),然后设置css的transition,overflow属性。

<div id="dom_id" >
    <div>something dangerous</div>
    <!-- <div>丝滑</div> -->
    <div>丝滑</div>
</div>
<div class="btn" data-status="show" onclick="slideToogle(event,'dom_id',500)">切换</div>
    
<script>
    function slideToogle(e,el,duration=1000){
        var dom = document.getElementById(el)
        var status = e.target.dataset.status
        var flag = e.target.dataset.status == 'show' //保存当前的状态,方便对显示或者隐藏进行判断
        e.target.dataset.status = flag?'hide':'show' //如果本来是show,现在就更改为隐藏,懒省事的写法
        dom.style.transition = 'height '+duration/1000+'s' //设置动画时间
        dom.style.overflow = 'hidden'     //保证子元素不外溢
        animateDom(flag,dom,duration)     //操作dom的height属性
    }
</script>

操作dom时需要注意的点

function animateDom(flag,dom,duration){    
    clearTimeout(dom.tagTimer);  // 清除定时器,因为连续点击会产生很多定时器,避免同时作用于dom
    setData(dom);                // 这个函数主要是设置一下属于当前dom的tagTimer,以及保存初始化高度tagHeight
    dom.style.height = flag?dom.tagHeight:"0px"  //这一行代码是初始化height属性,免得transition效果不触发,
    setTimeout(()=>{
        //这个定时器只是为了让js异步执行这两行代码,从而产生transition的过渡效果
        dom.style.height = flag?"0px":dom.tagHeight    //如果是显示,那就设置为原始高度,不显示就设置为0px
    },0)
    dom.tagTimer = setTimeout(()=>{
        //动画结束以后设置 显示状态,并且把相关属性清空,这样更清爽,不是么?
        dom.style.display = flag?'none':'block'
        dom.style.transition = '';
        dom.style.overflow = '';
        dom.style.height = '';
    },duration)
}

function setData(dom){    //这个就不多说了,理解一下
    dom.tagTimer = dom.tagTimer || null
    dom.style.display = 'block';
    dom.tagHeight = dom.tagHeight || dom.clientHeight+'px'
    dom.style.display = '';
}

猜你喜欢

转载自www.cnblogs.com/the-artist/p/12668551.html