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项目如何引入bootstrap、elementUI、echarts
Nov 26 Vue.js
vue动态合并单元格并添加小计合计功能示例
Nov 26 Vue.js
Vue+element-ui添加自定义右键菜单的方法示例
Dec 08 Vue.js
vue+elementUI动态增加表单项并添加验证的代码详解
Dec 17 Vue.js
vue监听滚动事件的方法
Dec 21 Vue.js
如何在vue-cli中使用css-loader实现css module
Jan 07 Vue.js
详解实现vue的数据响应式原理
Jan 20 Vue.js
详解vite+ts快速搭建vue3项目以及介绍相关特性
Feb 25 Vue.js
Vue+TypeScript中处理computed方式
Apr 02 Vue.js
vue-cil之axios的二次封装与proxy反向代理使用说明
Apr 07 Vue.js
vue3语法糖内的defineProps及defineEmits
Apr 14 Vue.js
vue二维数组循环嵌套方式 循环数组、循环嵌套数组
Apr 24 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
如何选购合适的收音机
2021/03/01 无线电
自己动手做一个SQL解释器
2006/10/09 PHP
PHP冒泡排序算法代码详细解读
2011/07/17 PHP
用PHP生成excel文件到指定目录
2015/06/22 PHP
php实现微信企业号支付个人的方法详解
2017/07/26 PHP
基于prototype的validation.js发布2.3.4新版本,让你彻底脱离表单验证的烦恼
2006/12/06 Javascript
js 小数取整的函数
2010/05/10 Javascript
NodeJS url验证(url-valid)的使用方法
2013/11/18 NodeJs
jQuery实现的超酷苹果风格图标滑出菜单效果代码
2015/09/16 Javascript
jquery实现鼠标悬浮停止轮播特效
2020/08/20 Javascript
获取今天,昨天,本周,上周,本月,上月时间(实例分享)
2017/01/04 Javascript
jQuery树控件zTree使用方法详解(一)
2017/02/28 Javascript
bootstrap daterangepicker双日历时间段选择控件详解
2017/06/15 Javascript
解决vue打包css文件中背景图片的路径问题
2018/09/03 Javascript
实例讲解JavaScript截取字符串
2018/11/30 Javascript
layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)
2019/09/23 Javascript
浅谈Ant Design Pro 菜单自定义 icon
2020/11/17 Javascript
[52:52]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第三局
2016/02/27 DOTA
python单元测试unittest实例详解
2015/05/11 Python
python基于右递归解决八皇后问题的方法
2015/05/25 Python
Python中将字典转换为XML以及相关的命名空间解析
2015/10/15 Python
全面分析Python的优点和缺点
2018/02/07 Python
python获取交互式ssh shell的方法
2019/02/14 Python
python利用wx实现界面按钮和按钮监听和字体改变的方法
2019/07/17 Python
python如何获取apk的packagename和activity
2020/01/10 Python
Anaconda+Pycharm环境下的PyTorch配置方法
2020/03/13 Python
python 模块导入问题汇总
2021/02/01 Python
HTML5轻松实现全屏视频背景的示例
2018/04/23 HTML / CSS
成功的餐厅经营创业计划书
2014/01/15 职场文书
大学国际贸易专业自荐信
2014/06/05 职场文书
小学生九一八纪念日83周年演讲稿500字
2014/09/17 职场文书
县人大领导班子四风对照检查材料思想汇报
2014/10/09 职场文书
2014年禁毒工作总结
2014/11/24 职场文书
家长通知书家长意见
2014/12/30 职场文书
《静夜思》教学反思
2016/02/17 职场文书
html网页引入svg图片的4种方式
2022/08/05 HTML / CSS