vue实现列表垂直无缝滚动


Posted in Vue.js onApril 08, 2022

本文实例为大家分享了vue实现列表垂直无缝滚动的具体代码,供大家参考,具体内容如下

实现新闻列表的轮播(如下图)

vue实现列表垂直无缝滚动

上代码

封装的so-marquee.vue

<template>
    <div
        class="marquee-wrapper"
        :style="{ width: realWidth + 'px' }"
    >
        <div
            class="marquee-container"
            :style="{ height: realHeight + 'px' }"
            :class="className"
        >
            <ul
                ref="marqueeCon"
                :id="tooltipId"
                class="marquee-content"
                :class="{ anim: animate === true}"
                @mouseenter="handleStop()"
                @mouseleave="handleUp()"
            >
                <li
                    v-for="(item,index) in realData"
                    :key="`${tooltipId}-${item.id}-${index}`"
                    class="marquee-item"
                    :style="{ height: itemHeigth + 'px' }"
                    @click="handleClick(item)"
                >
                    <slot name="itemCon" :item="item"></slot>
                </li>
            </ul>
        </div>
    </div>
</template>
<script>
import { parseToNum, generateId } from '@/utils/util'

export default {
    name: "so-marquee",
    props: {
        /*
        * 可接受传参
        * data          列表数据
        * className     自定义类名
        * width         列表宽度,默认值:400
        * height        列表高度,默认值:200
        * showNumber    可视的条目数,默认值:5
        * speed         轮播速度,默认值:1000
        * */
        //列表数据
        data: {
            type: Array,
            default: () => [],
        },
        //自定义类名
        className: String,
        //列表宽度,默认值:400
        width: {
            type: [Number, String],
            default: 400
        },
        //列表高度,默认值:200
        height: {
            type: [Number, String],
            default: 200
        },
        //可视的条目数,默认值:5
        showNumber: {
            type: [Number, String],
            default: 5
        },
        //轮播速度,默认值:1000
        speed: {
            type: [Number, String],
            default: 1000
        }
    },
    data() {
        return {
            intnum: undefined,
            animate: false
        };
    },
    computed: {
        tooltipId() {
            return `marquee-con-${ generateId() }`;
        },
        realWidth() {
            return parseToNum(this.width)
        },
        realHeight() {
            return parseToNum(this.height)
        },
        realShowNumber() {
            return parseToNum(this.showNumber)
        },
        realSpeed() {
            return parseToNum(this.speed) < 1000 ? 1000 : parseToNum(this.speed)
        },
        itemHeigth() {
            return this.realHeight / this.realShowNumber
        },
        realData() {
            return JSON.parse(JSON.stringify(this.data))
        }
    },
    mounted() {
        if (this.realData.length > this.realShowNumber) {
            this.scrollUp();
        }
    },
    methods: {
        scrollUp() {
            // eslint-disable-next-line no-unused-vars
            this.intnum = setInterval(_ => {
                this.animate = true;
                setTimeout(() => {
                    this.realData.push(this.realData[0]);   // 将数组的第一个元素添加到数组的
                    this.realData.shift();               //删除数组的第一个元素
                    this.animate = false;           // margin-top 为0 的时候取消过渡动画,实现无缝滚动
                }, this.realSpeed / 2)
                this.$once('hook:beforeDestroy', () => {
                    this.cleanup()
                })
            }, this.realSpeed);
        },
        handleStop() {
            this.cleanup()
        },
        handleUp() {
            this.scrollUp();
        },
        handleClick(row) {
            this.$emit('handleClick', row)
        },
        cleanup() {
            if (this.intnum) {
                clearInterval(this.intnum);
                this.intnum = null;
            }
        }
    },
    beforeDestroy() {
        this.cleanup();
    },
    deactivated() {
        this.cleanup();
    },
    watch: {
        animate(flag) {
            this.marqueeCon = this.$refs.marqueeCon
            if (flag) {
                this.marqueeCon.style.marginTop = `-${ this.itemHeigth }px`
            } else {
                this.marqueeCon.style.marginTop = 0
            }
        },
    }
};
</script>
<style scoped lang="scss">
    .marquee-container {
        overflow: hidden;
    }

    .marquee-content {
        position: relative;
    }

    .anim {
        transition: all 0.5s;
    }

    .marquee-item {
        display: flex;
        align-items: center;
        justify-content: space-around;
    }
</style>

parseToNum方法

export function parseToNum(value) {
    if (value !== undefined) {
        value = parseInt(value, 10)
        if (isNaN(value)) {
            value = null;
        }
    }
    return value
}

generateId 方法

export const generateId = function() {
    return Math.floor(Math.random() * 10000);
};

父组件调用

<template>
    <div id="app">
        <so-marquee
            :data="jsonData"
            :height="200"
            :showNumber="4"
            :speed="500"
            class="my-ui-marquee"
            @handleClick="handleMarqueeClick"
        >
            <template v-slot:itemCon="{item}">
                <div>{{ item.id }}</div>
                <div>{{ item.name }}</div>
                <div>{{ item.date }}</div>
            </template>
        </so-marquee>
    </div>
</template>

<script>
import soMarquee from './components/so-marquee'

export default {
    name: 'App',
    data() {
        return {
            jsonData: [
                {
                    id: 1,
                    name: "开会通知",
                    date: "2020-02-01"
                },
                {
                    id: 2,
                    name: "放假通知",
                    date: "2020-02-02"
                },
                {
                    id: 3,
                    name: "停水通知",
                    date: "2020-02-03"
                },
                {
                    id: 4,
                    name: "停电通知",
                    date: "2020-02-04"
                },
                {
                    id: 5,
                    name: "停车通知",
                    date: "2020-02-05"
                },
                {
                    id: 6,
                    name: "奖励通知",
                    date: "2020-02-06"
                },
                {
                    id: 7,
                    name: "处分通知",
                    date: "2020-02-07"
                },
                {
                    id: 8,
                    name: "处分8通知",
                    date: "2020-02-08"
                },
                {
                    id: 9,
                    name: "处分9通知",
                    date: "2020-02-09"
                },
                {
                    id: 10,
                    name: "处分10通知",
                    date: "2020-02-10"
                },
            ]
        }
    },
    components: {
        soMarquee
    },
    methods: {
        handleMarqueeClick(row) {
            alert(`当前点击的第${row.id}行`)
        }
    }
}
</script>

<style scoped lang="scss">
.my-ui-marquee {
    ::v-deep.marquee-item {
        cursor: pointer;
    }
}
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Vue.js 相关文章推荐
详解vue 组件注册
Nov 20 Vue.js
vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例
Nov 20 Vue.js
在Vue中使用CSS3实现内容无缝滚动的示例代码
Nov 27 Vue.js
Vue实现简单购物车功能
Dec 13 Vue.js
vue图片裁剪插件vue-cropper使用方法详解
Dec 16 Vue.js
vue实现拖拽进度条
Mar 01 Vue.js
vue3.0封装轮播图组件的步骤
Mar 04 Vue.js
如何理解Vue简单状态管理之store模式
May 15 Vue.js
idea编译器vue缩进报错问题场景分析
Jul 04 Vue.js
vue动态绑定style样式
Apr 20 Vue.js
vue3不同环境下实现配置代理
May 25 Vue.js
Vue2项目中对百度地图的封装使用详解
Jun 16 Vue.js
vue3引入highlight.js进行代码高亮的方法实例
vue中的可拖拽宽度div的实现示例
vue 实现弹窗关闭后刷新效果
Apr 08 #Vue.js
vue中this.$http.post()跨域和请求参数丢失的解决
Apr 08 #Vue.js
vue实现书本翻页动画效果实例详解
Apr 08 #Vue.js
vue实现列表拖拽排序的示例代码
vue实现可以快进后退的跑马灯组件
Apr 08 #Vue.js
You might like
DOTA2 探索永无止境 玩家自创强悍插眼攻略
2020/04/20 DOTA
在 PHP 中使用随机数的三个步骤
2006/10/09 PHP
php 获得汉字拼音首字母的函数
2009/08/01 PHP
php实现MySQL数据库备份与还原类实例
2014/12/09 PHP
php插入排序法实现数组排序实例
2015/02/16 PHP
document.open() 与 document.write()的区别
2007/08/13 Javascript
Flash+XML滚动新闻代码 无图片 附源码下载
2007/11/22 Javascript
JQuery中$之选择器用法介绍
2011/04/05 Javascript
javascript中判断一个值是否在数组中并没有直接使用
2012/12/17 Javascript
JS实现判断滚动条滚到页面底部并执行事件的方法
2014/12/18 Javascript
jQuery中[attribute^=value]选择器用法实例
2014/12/31 Javascript
jQuery实现单击和鼠标感应事件
2015/02/01 Javascript
js实现页面跳转的五种方法推荐
2016/03/10 Javascript
vueJS简单的点击显示与隐藏的效果【实现代码】
2016/05/03 Javascript
微信小程序 http请求详细介绍
2016/10/09 Javascript
js 转json格式的字符串为对象或数组(前后台)的方法
2016/11/02 Javascript
Nodejs实现短信验证码功能
2017/02/09 NodeJs
AngularJS实用基础知识_入门必备篇(推荐)
2017/07/10 Javascript
关于vue中 $emit的用法详解
2018/04/12 Javascript
vue webpack打包后图片路径错误的完美解决方法
2018/12/07 Javascript
封装Vue Element的table表格组件的示例详解
2020/08/19 Javascript
[03:57]2016完美“圣”典风云人物:rOtk专访
2016/12/09 DOTA
[38:54]完美世界DOTA2联赛PWL S2 Rebirth vs LBZS 第一场 11.28
2020/12/01 DOTA
Python二分法搜索算法实例分析
2015/05/11 Python
使用Python导出Excel图表以及导出为图片的方法
2015/11/07 Python
详解python发送各类邮件的主要方法
2016/12/22 Python
老生常谈python函数参数的区别(必看篇)
2017/05/29 Python
Python3中的json模块使用详解
2018/05/05 Python
如何使用Python多线程测试并发漏洞
2019/12/18 Python
python使用scapy模块实现ARP扫描的过程
2021/01/21 Python
Orlebar Brown官网:设计师泳裤和泳装
2020/12/08 全球购物
写给女生的道歉信
2014/01/08 职场文书
企业宣传策划方案
2014/05/29 职场文书
水利水电建筑施工应届生求职信
2014/07/04 职场文书
学校感恩教育活动总结
2014/07/07 职场文书
MySQL创建索引需要了解的
2021/04/08 MySQL