原生JS实现下拉刷新、上拉加载

最近部门移动端需要实现一个评价列表查询的功能,由于之前没有实现过,因此找了第三方库来实现,前前后后磕磕碰碰的花了一个小时终于实现了一个上拉刷新、下拉加载的功能。虽然实现了该功能,但是毕竟使用的是第三方库的组件,一旦出啥问题也不好解决,想了想,反正部门内部的组件库没有上拉刷新、下拉加载的组件,那么我何不写一个这样的组件呢?于是下定决心为部门组件库增加该组件。

先上效果

image

聊聊实现思路

移动端下拉刷新、上拉加载主要基于H5的三个事件完成,分别是 touchstart、touchmove、touchend。三者绑定在任意元素上。
touchstart:顾名思义,就是手指第一次触摸到所绑定的元素时所触发的事件。
touchmove:顾名思义,就是手指在绑定的元素中滑动时触发的事件。
touchend:顾名思义,急速手指松开时触发的事件。
基于上述三者,我们就可以获取某一元素的触摸、滑动、松开的事件,但是只是获取到事件是没法让元素滑动的,那么问题来了,如何让元素滑动?
让元素滑动主要是基于css3中的transform:translateY;属性,它可以让一个元素基于原始位置向X、Y轴移动一定的像素距离。例如transform:translateY(50px);

这样就可以利用 touchstart、touchmove、touchend 和 transform来实现下拉刷新、上拉加载的功能了。

为了避免效果不好,于是我先用原生写了上拉刷新、下拉加载的功能。

后期会发出基于VUE的上拉刷新、下拉加载组件。

话不多说,Show Code...

这是body部分

<body>
    <div id="warper" style="width: 100%;font-size: 100px;">
        <div class="topbar">
            Topbar
        </div>
        <div id="refresh">
        </div>
        <ul id="content">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
        <div id="loading">
            <p>加载中...</p>
        </div>
    </div>
</body>

这是JS部分

<script type="text/javascript">
    var startWZ //记录鼠标点击的位置
    var moveWZ  // 记录移动的位置
    var distance // 记录移动的距离
    var timer   // 定时器id
    var rule = 100 // 定义触发加载刷新事件的拉伸长度
    document.getElementById('content').addEventListener('touchstart',function (e) {
        startWZ = e.touches[0].screenY - distance//获取每次点击的开始位置 减去上次剩余的距离
    }, false)

    document.getElementById('content').addEventListener('touchmove', function (e) {
        moveWZ = e.touches[0].screenY //获取每次鼠标移动的位置
        distance = Math.floor(moveWZ - startWZ) // 求出移动的距离
        beforeAction(distance) //刷新和加载之前的UI处理
        document.getElementById('content').style.transform = `translateY(${distance}px)` //元素同步鼠标移动
    }, false)

    document.getElementById('content').addEventListener('touchend', function (e) {
        if (timer) clearInterval(timer) //防止多次拉动创建多个定时器
        // 收缩处理
        timer = setInterval(() => {
                //  取整复位
            if (Math.floor(distance) === 0 || Math.ceil(distance) === 0) {
                document.getElementById('content').style.transform = `translateY(0px)`
                clearInterval(timer) //收缩完成
            } else {
                    // 百分比收缩
                distance -= distance/50
                document.getElementById('content').style.transform = `translateY(${distance}px)`
            }
        },10)
        // 拉伸距离大于指定值才进行 刷新 加载事件
        if (distance > rule) refresh()
        if (distance < -rule) loading()
    }, false)
    // UI处理
    function beforeAction (distance) {
        if (distance > rule) {
            var el = document.getElementById('refresh')
            el.innerHTML = '<p>刷新中...</p>'
            el.style.display = 'block'
        } else {
            document.getElementById('refresh').style.display = 'none'
        }
        if (distance < -rule) {
            document.getElementById('loading').style.display = 'block'
        } else {
            document.getElementById('loading').style.display = 'none'
        }
    }
        // 刷新逻辑在此处理
    function refresh (callback) {
        setTimeout(() => {
            var el = document.getElementById('refresh')
            el.innerHTML = '<p>刷新成功!</p>'
            setTimeout(() => {el.style.display = 'none'}, 300)
        }, 1000)
    }
        // 加载逻辑在此处理
    function loading (callback) {
        let li = document.createElement('li')
        li.innerHTML = "我是新加载的元素"
        setTimeout(() => {
            document.getElementById('content').appendChild(li)
            document.getElementById('loading').style.display = 'none'
        },2000)
    }
</script>

这是CSS部分

<style type="text/css">
    * {
        padding: 0;
        margin: 0;
    }
    li {
        list-style-type:none;   
    }
    .topbar {
        background-color: #7777;
    }
    #refresh, #loading {
        background-color: red;
        font-size: 50px;
        text-align: center;
        height: 60px;
        line-height: 60px;
        display: none;
    }
</style>

总结

活到老学到老...
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。