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+iview实现分页及查询功能
Nov 17 Vue.js
详解vue实现坐标拾取器功能示例
Nov 18 Vue.js
浅析VUE防抖与节流
Nov 24 Vue.js
详解Vue 的异常处理机制
Nov 30 Vue.js
Vue实现指令式动态追加小球动画组件的步骤
Dec 18 Vue.js
Vue实现随机验证码功能
Dec 29 Vue.js
Vue 集成 PDF.js 实现 PDF 预览和添加水印的步骤
Jan 22 Vue.js
Vue 数据响应式相关总结
Jan 28 Vue.js
使用Vue.js和MJML创建响应式电子邮件
Mar 23 Vue.js
vue实现水波涟漪效果的点击反馈指令
May 31 Vue.js
Vue的过滤器你真了解吗
Feb 24 Vue.js
分享一个vue实现的记事本功能案例
Apr 11 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
基于Zookeeper的使用详解
2013/05/02 PHP
php数组函数array_key_exists()小结
2015/12/10 PHP
php pthreads多线程的安装与使用
2016/01/19 PHP
PHP验证码生成原理和实现
2016/01/24 PHP
浅谈php中curl、fsockopen的应用
2016/12/10 PHP
使用php完成常见的文件上传功能(推荐)
2017/01/13 PHP
简略的前端架构心得&amp;&amp;基于editor为例子的编码小技巧
2010/11/25 Javascript
js中创建对象的几种方式示例介绍
2014/01/26 Javascript
js/jquery获取文本框输入焦点的方法
2014/03/04 Javascript
超级简单的jquery操作表格方法
2014/12/15 Javascript
BootStrap的弹出框(Popover)支持鼠标移到弹出层上弹窗层不隐藏的原因及解决办法
2016/04/03 Javascript
JavaScript无阻塞加载和defer、async详解
2017/02/26 Javascript
ES6中Math对象新增的方法实例详解
2017/04/25 Javascript
angular+webpack2实战例子
2017/05/23 Javascript
jQuery动态操作表单示例【基于table表格】
2018/12/06 jQuery
JS实现随机抽取三人
2019/11/06 Javascript
微信小程序webSocket的使用方法
2020/02/20 Javascript
微信小程序开发之获取用户手机号码(php接口解密)
2020/05/17 Javascript
node.js如何操作MySQL数据库
2020/10/29 Javascript
Vue 实现拨打电话操作
2020/11/16 Javascript
vue实现按钮切换图片
2021/01/20 Vue.js
[00:35]DOTA2上海特级锦标赛 Newbee战队宣传片
2016/03/03 DOTA
django 实现将本地图片存入数据库,并能显示在web上的示例
2019/08/07 Python
在Python中通过threshold创建mask方式
2020/02/19 Python
基于python实现监听Rabbitmq系统日志代码示例
2020/11/28 Python
CSS3制作精致的照片墙特效
2016/06/07 HTML / CSS
canvas画图被放大且模糊的解决方法
2020/08/11 HTML / CSS
介绍一下你对SOA的认识
2016/04/24 面试题
老师自我鉴定范文
2013/12/25 职场文书
《诺贝尔》教学反思
2014/02/17 职场文书
2014年小学植树节活动方案
2014/03/02 职场文书
电子商务专业自荐信
2014/06/02 职场文书
黑暗中的舞者观后感
2015/06/18 职场文书
详解nginx.conf 中 root 目录设置问题
2021/04/01 Servers
浅谈node.js中间件有哪些类型
2021/04/29 Javascript
MySql中的json_extract函数处理json字段详情
2022/06/05 MySQL