一鱼三吃:自动轮播图-vue版

缘由:某天在某群瞟了一眼,有人在找轮播图,,,

想想,自己来写一个,(可能的话,分别用vue、react、angular)

找了某老师用原生js写的轮播图,研究了一下,研究的结果大体如下:

html文档结构:

外层一个div 容器,包裹 2 个子元素,第一个子元素div包裹一个Ul列表,每个li元素包裹一个img元素,即需要显示的图片。第二个子元素是一个ul列表,具体效果见下面的截图:

解析:

1, 第2个ul列表,即按钮,由代码动态生成。

2,设置计时器,每3秒调用移动函数,此函数重设图片列表容器list的top值 

3,按钮添加Mouseover事件,触发事件,则图片切换至按钮关联图片

tips:在css中,已经把class为list的图片容器div设置为 position:relative;设置图片ul为position:absolute;

此时,5张图上由上到下,排列为一张大图片,,只需要定时更改ul的style属性top,即可显示不同的图片。

------------------------------------------------------分割线---------------------------------------------------------------------------

现在改为用vue来重构

1,在图片列表ul上,绑定style为一个样式对象:stlyes。此styles是一个对象字面量,包含一个属性top,默认值为0。

  <ul :style="styles">
        <li><img src="./img/01.jpg" width="490" height="170"></li>
                <li><img src="./img/02.jpg" width="490" height="170" /></li>
                <li><img src="./img/03.jpg" width="490" height="170" /></li>
                <li><img src="./img/04.jpg" width="490" height="170" /></li>
                <li><img src="./img/05.jpg" width="490" height="170" /></li>
      </ul>

留意ul列表所绑定的动态属性,我们将通过定时更改Ul图片列表的top值,来达到让图片动起来的效果。

a首先,让图片动起来,为此,我们需要先定义 cutover 函数,此函数会调用移动函数 startMove,让图片动起来,我们给此函数传入了一个移动值,即需要移动的距离,170为图片高度,这里硬编码了,原生应用中是通过js来获取图片的高度的,index则是图片索引,表明需要移动至第几张图片

cutover(){      
      this.startMove(-(this.index * 170))
    },

定义了此函数后,需要先初始化,也就是把它放在组件钩子函数 created中;

  created(){
    this.cutover();
    this.playTimer = setInterval(this.next,3000)
  }

b 要让图片连续不断的动起来,还需要一个计时器,此计时器调用一个next函数,此函数作了这样几件事:根据bOrder,一个bool值,来判断图片索引值index应该递增/递减,接着,判断Index值是否溢出,因为图片总共 5 张,则index 的值被限制在了 0 至4之间。(这里硬编码了)随后调用 cutover

  next(){
      this.bOrder ? this.index++ : this.index--;
      this.index <= 0 && (this.index=0,this.bOrder=true);
      this.index >= 4 && (this.index=4, this.bOrder = false);
      this.cutover();
    },

c到此,图片加载后,每隔 3 秒钟,就会自动向上移动,移动至第5张图片后,随后向下移动,依次显示图片。

如果打开浏览器,会发现图片切换时,很生硬,因为移动得很快,要想让移动显得柔和一点,需要调整下移动图片的速度,不能一次到位。所以负责移动的函数 startMove()又做了以下一些事情 :

    startMove(distance){
      clearInterval(this.timer);

      this.timer=setInterval(()=>
      this.doMove(distance),30)
    },
    doMove(distance){
      var iSpeed = (distance - parseInt(this.styles.top)) / 10;
      iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
      parseInt(this.styles.top)==distance ? clearInterval(this.timer) : this.styles.top = parseInt(this.styles.top) + iSpeed + 'px';
    }

2 我们还需要实现一个效果,即图片上一列按钮,分别关联着对应的图片,当鼠标按钮mouseover到按钮,会显示对应的图片

a首先,不再直接操作dom来生成按钮列表,改为在template中布局:

  <ul class="count">
      <li v-for="i in 5" :key="i-1"
      @mouseover="handleButtonOver(i-1)"
      :class="classes(i-1)"
      >{{ i}}</li>
    </ul>

仔细阅读上面的代码,可以看到,我们在每一个li元素上,为mouseover事件绑定了一个处理器,绑定了一个动态类,这里使用了一个函数,而没有使用计算性属性,因为函数才能接受参数

    handleButtonOver(num){     
      this.index = num;
      this.cutover();
    },
    classes(num){
      return[
        {
          'current':this.index==num
        }
      ]
    },

至此,我们的轮播图应用大体成型了。

完整的代码见下图:

<template>
  <div id="box" @mouseover="handleOver" @mouseout="handleOut">
    <div class="list" >
      <ul :style="styles">
        <li><img src="./img/01.jpg" width="490" height="170"></li>
                <li><img src="./img/02.jpg" width="490" height="170" /></li>
                <li><img src="./img/03.jpg" width="490" height="170" /></li>
                <li><img src="./img/04.jpg" width="490" height="170" /></li>
                <li><img src="./img/05.jpg" width="490" height="170" /></li>
      </ul>
    </div>  
    <ul class="count">
      <li v-for="i in 5" :key="i-1"
      @mouseover="handleButtonOver(i-1)"
      :class="classes(i-1)"
      >{{ i}}</li>
    </ul>
  </div> 
</template>

<script>
//import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    
  },
  data(){    
    return{
      styles:{
        top:0
      },
      index:0,
      bOrder:true,
      timer:null,
      playTimer:null,
    }
  },  
  methods:{
    handleButtonOver(num){     
      this.index = num;
      this.cutover();
    },
    classes(num){
      return[
        {
          'current':this.index==num
        }
      ]
    },
    handleOver(){
      clearInterval(this.playTimer);
    },
    handleOut(){
      this.playTimer = setInterval(this.next,3000);
    },
    cutover(){      
      this.startMove(-(this.index * 170))
    },
    next(){
      this.bOrder ? this.index++ : this.index--;
      this.index <= 0 && (this.index=0,this.bOrder=true);
      this.index >= 4 && (this.index=4, this.bOrder = false);
      this.cutover();
    },
    startMove(distance){
      clearInterval(this.timer);

      this.timer=setInterval(()=>
      this.doMove(distance),30)
    },
    doMove(distance){
      var iSpeed = (distance - parseInt(this.styles.top)) / 10;
      iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
      parseInt(this.styles.top)==distance ? clearInterval(this.timer) : this.styles.top = parseInt(this.styles.top) + iSpeed + 'px';
    }
  },
  created(){
    this.cutover();
    this.playTimer = setInterval(this.next,3000)
  }
}
</script>

 

posted @ 2021-01-05 22:40  sx00xs  阅读(175)  评论(0编辑  收藏  举报