一个简单的Vue2消息上下滚动组件

174 阅读1分钟

一、使用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>