服务器之家:专注于服务器技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - vue.js - vue下拉刷新组件的开发及slot的使用详解

vue下拉刷新组件的开发及slot的使用详解

2021-12-16 15:43行舟客 vue.js

这篇文章主要介绍了vue下拉刷新组件的开发及slot的使用详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

“下拉刷新”和“上滑加载更多”功能在前端、尤其是移动端项目中非常重要,这里笔者由曾经做过的vue项目中的“blink”功能和各位探讨下【下拉刷新】组件的开发:

正式开篇

在前端项目的 components 文件夹下新建 pullRefreshView 文件夹,在其中新建组件 index.vue:(它代表“整个屏幕”,通过slot插入页面其他内容而不是传统的设置遮罩层触发下拉刷新)

首先需要编写下拉刷新组件的 template,这里用到 <slot>,代码如下:

?
1
2
3
4
5
6
7
8
<template>
    <div class="pullRefreshView" @touchmove="touchmove" @touchstart="touchstart" @touchend="touchend">
        <div ref="circleIcon" class="circle-icon">
            <div ref="circleIconInner" class="circle-icon-inner"></div>
        </div>
        <slot></slot>
    </div>
</template>

上面代码中,最外层使用了一个 div 用来包裹,作为事件绑定的容器,同时新建一个圆形 icon 的 div .circleIcon,我们将此 icon 样式设置在屏幕外,达到隐藏的效果,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<style>
    .circle-icon{
        position: absolute;
        left: 0.625rem;
        top: -1.875rem;
    }
    .circle-icon-inner{
        width: 1.5625rem;
        height: 1.5625rem;
        background-image: url('圆圈图片地址');
        background-size: cover;
    }
    .circle-rotate{
        animation: xuzhuan .8s linear infinite;
    }
    @keyframes xuzhuan{
        0%{}
        25%{}
        50%{}
        75%{}
        100%{}
    }
</style>

下拉刷新组件的 UI 基本编写完毕,接下来就要绑定事件了,通过上述分析,加上我们之前章节开发图片查看器的原理,我们需要用到移动端 touchstart,touchmove,touchend 事件,可以实现下拉刷新效果。

首先,监听 touchstart 事件:

?
1
2
3
4
touchstart(evt){
    this.pullRefresh.dragStart=evt.targetTouches[0].clientY
    this.$refs.circleIcon.style.webkitTransition='none'
},

在 touchstart 事件中,我们主要做的是记录一些初始值,包括手指第一次接触屏幕时的位置,然后将圆形 icon 的动画效果先隐藏。

然后,监听 touchmove 事件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
touchmove(evt){
    if(this.pullRefresh.dragStart===null){
        return
    }
    let target=evt.targetTouches[0]
    // 向上滑为正,向下拉为负
    this.pullRefresh.percentage=(this.pullRefresh.dragStart-target.clientY)/window.screen.height
    let scrollTop=document.documentElement.scrollTop || document.body.scrollTop
    if(scrollTop===0){
        //this.pullRefresh指data中的pullRefresh对象(下方有),而evt即事件event参数
        if(this.pullRefresh.percentage<0 && evt.cancelable){
            evt.preventDefault()
            this.pullRefresh.joinRefreshFlag=true
            let translateY=-this.pullRefresh.percentage*this.pullRefresh.moveCount
            if(Math.abs(this.pullRefresh.percentage)<=this.pullRefresh.dragThreshold){
                let rotate=translateY/30*360
                this.$refs.circleIcon.style.webkitTransform='translate3d(0'+translateY+'px,0) rotate('+rotate+'deg)'
            }
        }else{
            if(this.pullRefresh.joinRefreshFlag===null){
                this.pullRefresh.joinRefreshFlag=false
            }
        }
    }else{
        if(this.pullRefresh.joinRefreshFlag===null){
            this.pullRefresh.joinRefreshFlag=false
        }
    }
},

在 touchmove 事件里,我们主要做的是根据手指移动的量来实时将圆形 icon 移动并旋转,这里有几点确实要说明一下:

  • 我们的下拉刷新触发的时机是在页面处于屏幕顶部并且手指向下拖动,这两个条件,缺一不可,在代码中,我们利用 scrollTop == 0this.pullRefresh.percentage < 0 来判断。
  • 在进入下拉刷新状态时,此时手指不断向下拖动,首先圆形 icon.circleIcon 会向下滚动并旋转,当滚动到临界值时就只原地旋转。
  • 如果手指在向上拖动,圆形 icon.circleIcon 就会向上滚动并旋转。
  • 直到手指离开屏幕前,都不会触发下拉刷新,只是圆形 icon.circleIcon 在不停的上下移动。

监听 touchend 事件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
touchend(evt){
    if(this.pullRefresh.percentage===0){
        return
    }
    if(Math.abs(this.pullRefresh.percentage)>this.pullRefresh.dragThreshold && this.pullRefresh.joinRefreshFlag){
        this.$emit('onRefresh')
        this.$refs.circleIconInner.classList.add('circle-rotate')
        setTimeout(()=>{
            this.$refs.circleIconInner.classList.remove('circle-rotate')
            this.$refs.circleIcon.style.webkitTransition='330ms'
            this.$refs.circleIcon.style.webkitTransform='translate3d(0,0,0) rotate(0deg)'
        },700)
    }else{
        if(this.pullRefresh.joinRefreshFlag){
            this.$refs.circleIcon.style.webkitTransition='330ms'
            this.$refs.circleIcon.style.webkitTransform='translate3d(0,0,0) rotate(0deg)'
        }
    }
    this.pullRefresh.joinRefreshFlag=null
    this.pullRefresh.dragStart=null
    this.pullRefresh.percentage=0
}

在 touchend 事件中,我们主要是做一些动画执行的操作,大家可以看看代码中的注释,这里说明一下:

  1. 此时手指离开屏幕,位移量达到临界值时,并且也有进入下拉刷新的标志位,就表明要触发正在刷新。此时圆形 icon原地旋转,并触发下拉刷新回调方法,延迟 700ms 后向上收起。
  2. 我们在实现圆形 icon 时的旋转和位移动画时,用了两个 div,在 touchmove 时,我们主要对外层的 div 也就是 ref=circleIcon,来实现位移和旋转。
  3. 在 touchend 时,我们主要给内层的 div 也就是 ref=circleIconInner 来加 animation 动画,因为无法给一个 div 同时使用位移旋转和 animation 动画,所以这里一个技巧就是给父元素设置位移和旋转,它的子元素在不设置任何 CSS 动画样式时,是会随着父元素而生效的。

最后,我们看下【data】中都有什么:

?
1
2
3
4
5
6
7
8
9
10
11
data(){
    return{
        pullRefresh:{
            dragStart:null, //开始抓取标志位
            percentage:0, //拖动量(百分比)
            dragThreshold:0.3, //临界值
            moveCount:200, //位移系数,可以调节圆形图片icon的运动速率
            joinRefreshFlag:null, //进入刷新状态的标志位(true)
        }
    }
},

补充:slot

<template>中为什么有<slot>

slot有三种形式:

  1. 普通插槽
  2. 具名插槽
  3. 作用域插槽

可能我们一般用具名slot的时候比较多,但是第一种也格外好用——正因为它没有名字,所以引用这个组件的另一个组件中包裹其中的所有内容都归这个slot所有:

假定my-component组件中有如下模板:

?
1
2
3
4
<div>
    <h2>我是子组件</h2>
    <slot>只有在没有内容分发的情况下这句话才会出现</slot>
</div>

父组件模板:

?
1
2
3
4
5
6
7
<div>
    <h1>这是父组件地盘</h1>
    <my-component>
        <p>这是一些初始内容</p>
        <p>这是更多的内容</p>
    </my-component>
</div>

最后就会被渲染成这样:

?
1
2
3
4
5
6
7
8
<div>
    <h1>这是父组件地盘</h1>
    <div>
        <h2>我是子组件</h2>
        <p>这是一些初始内容</p>
        <p>这是更多的内容</p>
    </div>
</div>

所以这里这样做,就是为了在“父组件”中调用时让“下拉的动画”更自然,但又不会增加一个文件的负担。

到此这篇关于vue下拉刷新组件的开发及slot的使用详解的文章就介绍到这了,更多相关vue下拉刷新组件slot使用内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_43624878/article/details/109252057

延伸 · 阅读

精彩推荐
  • vue.jsVue2.x-使用防抖以及节流的示例

    Vue2.x-使用防抖以及节流的示例

    这篇文章主要介绍了Vue2.x-使用防抖以及节流的示例,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下...

    Kyara6372022-01-25
  • vue.jsVue中引入svg图标的两种方式

    Vue中引入svg图标的两种方式

    这篇文章主要给大家介绍了关于Vue中引入svg图标的两种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    十里不故梦10222021-12-31
  • vue.jsVue项目中实现带参跳转功能

    Vue项目中实现带参跳转功能

    最近做了一个手机端系统,其中遇到了父页面需要携带参数跳转至子页面的问题,现已解决,下面分享一下实现过程,感兴趣的朋友一起看看吧...

    YiluRen丶4302022-03-03
  • vue.jsVue2.x 项目性能优化之代码优化的实现

    Vue2.x 项目性能优化之代码优化的实现

    这篇文章主要介绍了Vue2.x 项目性能优化之代码优化的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    优小U9632022-02-21
  • vue.js用vite搭建vue3应用的实现方法

    用vite搭建vue3应用的实现方法

    这篇文章主要介绍了用vite搭建vue3应用的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    Asiter7912022-01-22
  • vue.js详解vue 表单绑定与组件

    详解vue 表单绑定与组件

    这篇文章主要介绍了vue 表单绑定与组件的相关资料,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下...

    Latteitcjz6432022-02-12
  • vue.jsVue多选列表组件深入详解

    Vue多选列表组件深入详解

    这篇文章主要介绍了Vue多选列表组件深入详解,这个是vue的基本组件,有需要的同学可以研究下...

    yukiwu6752022-01-25
  • vue.js梳理一下vue中的生命周期

    梳理一下vue中的生命周期

    看过很多人讲vue的生命周期,但总是被绕的云里雾里,尤其是自学的同学,可能js的基础也不是太牢固,听起来更是吃力,那我就已个人之浅见,以大白话...

    CRMEB技术团队7992021-12-22