vue列表垂直无缝滚动
杨阳洋 人气:0实现新闻列表的轮播(如下图)
上代码
封装的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>
加载全部内容