一、使用transition实现
<template>
<div>
<div class="notice-box">
<transition name="notice-slide">
<div class="notice-item" :key="this.index">
<slot :currentNotice="currentNotice"></slot>
</div>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'scroll',
props: ['noticeArr', 'duration'],
data() {
return {
index: 0,
timer: null,
// flag: false,
}
},
computed: {
//当前滚动的消息
currentNotice() {
return this.noticeArr[this.index]
},
},
activated() {
this.scrollMove()
},
mounted() {
this.scrollMove()
},
deactivated() {
clearTimeout(this.timer)
this.timer = null
},
destroyed() {
clearTimeout(this.timer)
this.timer = null
},
methods: {
//滚动函数
scrollMove() {
if (this.timer !== null) {
return
}
this.timer = setInterval(() => {
if (this.index === this.noticeArr.length - 1) {
this.index = 0
} else {
this.index += 1
}
}, this.duration)
},
},
}
</script>
<style lang="scss" scoped>
.notice-box {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
.notice-item {
width: 100%;
height: 100%;
box-sizing: border-box;
position: absolute;
top: 0;
}
.notice-slide-enter-active,
.notice-slide-leave-active {
transition: all 0.5s;
}
.notice-slide-enter {
top: 30px;
}
.notice-slide-leave-to {
top: -30px;
}
</style>
transition方式实现代码比较简单易读,但使用这种方式某种情况下可能会影响到页面其他dom元素,可以使用第二种方式
二、使用setInterval实现
<template>
<div
class="notice-scroll-box"
:style="{ height: propsHeight, lineHeight: propsHeight }"
>
<div class="notice-scroll-list" :style="{ top: listTop + 'px' }">
<div v-for="(data, index) in slicedData" :key="index">
<slot :currentNotice="data"></slot>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'OfficialWebNoticeScrollBox',
props: {
//源数据
noticeArr: {
type: Array,
default: () => [],
},
//滚动间隔时间
duration: {
type: Number,
default: 3000,
},
//内容高度
propsHeight: {
type: Number,
default: 18,
},
//滚动速率
rate: {
type: Number,
default: 20,
},
},
data() {
return {
listTop: 0,
index: 3,
slicedData: [],
interval: null,
timer: null,
timer2: null,
}
},
mounted() {
console.log('mounted')
this.initScroll()
},
activated() {
console.log('activated')
this.initScroll()
},
deactivated() {
console.log('deactivated')
this.clear()
},
destroyed() {
console.log('destroyed')
this.clear()
},
methods: {
initScroll() {
this.initData()
this.clear()
this.timer2 = setTimeout(() => {
this.setScroll()
}, this.duration)
},
initData() {
if (this.noticeArr.length === 1) {
this.index = 0
this.slicedData = [this.noticeArr[0]]
} else if (this.noticeArr.length === 2) {
this.index = 1
this.slicedData = this.noticeArr.slice(0, 2)
} else {
this.index = 3
this.slicedData = this.noticeArr.slice(0, 3)
}
},
setScroll() {
if (this.noticeArr.length < 2) {
return
}
this.interval = setInterval(() => {
this.listTop--
if (this.listTop === Number('-' + this.propsHeight)) {
//数据循环
if (this.index === this.noticeArr.length) {
this.index = 0
}
//删除列表第一条数据
this.slicedData.shift()
//列表最后添加一条
this.slicedData.push(this.noticeArr[this.index++])
//重置top
this.listTop = 0
//取消定时器
clearInterval(this.interval)
//设置一个2秒后执行的定时器,重新开启滚动
this.timer = setTimeout(() => {
this.setScroll()
}, this.duration)
}
}, this.rate)
},
clear() {
clearTimeout(this.timer)
clearTimeout(this.timer2)
clearInterval(this.interval)
this.timer = null
this.timer2 = null
this.interval = null
this.listTop = 0
},
},
}
</script>
<style lang="scss" scoped>
.notice-scroll-box {
overflow: hidden;
position: relative;
.notice-scroll-list {
position: absolute;
left: 0;
}
}
</style>