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" onclick="slideToogle(event,'dom_id',500)">切換</div>
<script>
    function slideToogle(e,el,duration=1000){
        var dom = document.getElementById(el)
        dom.status = dom.status || getComputedStyle(dom,null)['display']
        var flag = dom.status != 'none' //保存當前的顯示狀態,方便進行判斷
        dom.status = flag?'none':'block' //更改dom上的顯示屬性
        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" onclick="slideToogle(event,'dom_id',500)">切換</div>
    
<script>
    function slideToogle(e,el,duration=1000){
        var dom = document.getElementById(el)
        dom.status = dom.status || getComputedStyle(dom,null)['display']
        var flag = dom.status != 'none'  //保存當前的顯示狀態,方便進行判斷
        dom.status = flag?'none':'block' //更改dom上的顯示屬性
        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 = '';
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM