zoukankan      html  css  js  c++  java
  • 用Vue实现一个简单的图片轮播

    本文已收录至https://github.com/likekk/studyBlog欢迎大家star,共同学习,共同进步。如果文章有错误的地方,欢迎大家指出。后期将在将GitHub上规划前端学习的路线和资源分享。

    写在前面

    每一篇文章都希望您有所收获,每一篇文章都希望您能静下心来浏览、阅读。每一篇文章都是作者精心打磨的作品。

    如果您觉得杨戬这个小白还有点东西的话,杨戬希望正在看文章的您可以帮忙点亮那个点赞的按钮(效果更加),对于杨戬这个暖男来说,真的真的非常重要,这将是我持续写作的动力。

    前言

    写这篇文章的目的主要是将以前所学的知识结合起来,进一步巩固一下自己的记忆,防止遗忘(主要是害怕老年痴呆),当然更重要的是学以致用,毕竟学过的东西不拿来用的话就会很容易忘记,永远不要太相信自己的记忆,编程这东西,几天不弄,忘的就很快,回过头再看,心里想着:这是我写的代码吗?本篇博客也是秉着这样的初心去写的。

    整体分析

    在我看来,我觉得做每一件事情都必须弄清楚这件事情的前因后果,当然了如果有是实在不太了解的,姑且可以先实现效果。

    然后再返回去慢慢理解,不过我一般比较喜欢先分析整体结构,然后一步一步去实现,有些事情不可能做到尽善尽美的,不是吗?先上效果图吧!

    这张图打了一波广告,我想你们应该不会介意的吧!不过说实话这里面的老师讲课真的是特别优秀,感兴趣的读者可以去尝试一下,毕竟暖男戬是不会骗人的。

    本来想着弄一下轮播图的动态效果的,奈何不会弄,所以放弃了,静态的凑合看吧!

    分析第一步

    布局的话,一个是显示图片,另一个是显示小圆点,图片切换的时候,小圆点也随着切换,当切换到最后一张的时候图片重从第一张开始重新轮播。

    分析第二步

    我们需要明确哪些数据是需要通过外部传输,哪些数据是我们自己可以控制,从效果图分析主要的话是图片,当然控制小圆点也是可以的,我们知道vue是可以实现组件的复用的,那么对于轮播图而言,也可以实现其复用性。

    例如:在其它地方我们也需要用到轮播图,但是轮播的图片不一样,轮播的速度不一样等等。

    总结:分析哪些数据是可控的,哪些数据是不可控的。

    分析第三步

    这里主要是轮播整体的实现,鼠标经过,轮播停止,鼠标移出,轮播继续,点击小圆点,实现轮播。

    涉及知识点

    文章中轮播图的实现涉及的知识点我整理了一下,如果有知识点不太清楚的读者可以去了解相关的内容。

    • vue的父子组件通信
    • 静态资源的导入
    • v-if和v-for的使用
    • 事件处理
    • class和sytle绑定
    • Vue的生命周期
    • 组件的校验

    轮播的实现

    将步骤分析和涉及的知识点整理之后,一切应该都是游刃有余吧!那么我们一步一步实现轮播的效果。

    界面布局

    1、全局css样式引入

    全局css样式,我已经会搭建准备好了,一个是reset.css,一个是global.css,静态图片资源放在了github上,大家可以自行下载

    reset.css

      1/* http://meyerweb.com/eric/tools/css/reset/ 
    2   v2.0 | 20110126
    3   License: none (public domain)
    4*/

    5
    6html,
    7body,
    8div,
    9span,
    10applet,
    11object,
    12iframe,
    13h1,
    14h2,
    15h3,
    16h4,
    17h5,
    18h6,
    19p,
    20blockquote,
    21pre,
    22a,
    23abbr,
    24acronym,
    25address,
    26big,
    27cite,
    28code,
    29del,
    30dfn,
    31em,
    32img,
    33ins,
    34kbd,
    35q,
    36s,
    37samp,
    38small,
    39strike,
    40strong,
    41sub,
    42sup,
    43tt,
    44var,
    45b,
    46u,
    47i,
    48center,
    49dl,
    50dt,
    51dd,
    52ol,
    53ul,
    54li,
    55fieldset,
    56form,
    57label,
    58legend,
    59table,
    60caption,
    61tbody,
    62tfoot,
    63thead,
    64tr,
    65th,
    66td,
    67article,
    68aside,
    69canvas,
    70details,
    71embed,
    72figure,
    73figcaption,
    74footer,
    75header,
    76hgroup,
    77menu,
    78nav,
    79output,
    80ruby,
    81section,
    82summary,
    83time,
    84mark,
    85audio,
    86video {
    87  margin0;
    88  padding0;
    89  border0;
    90  font-size100%;
    91  font: inherit;
    92  vertical-align: baseline;
    93}
    94/* HTML5 display-role reset for older browsers */
    95article,
    96aside,
    97details,
    98figcaption,
    99figure,
    100footer,
    101header,
    102hgroup,
    103menu,
    104nav,
    105section {
    106  display: block;
    107}
    108body {
    109  line-height1;
    110}
    111ol,
    112ul {
    113  list-style: none;
    114}
    115blockquote,
    116q {
    117  quotes: none;
    118}
    119blockquote:before,
    120blockquote:after,
    121q:before,
    122q:after {
    123  content"";
    124  content: none;
    125}
    126table {
    127  border-collapse: collapse;
    128  border-spacing0;
    129}

    global.css

     1@import "//at.alicdn.com/t/font_1811699_2hvkwp7upcz.css";
    2
    3a {
    4  color#409eff;
    5  text-decoration: none;
    6}
    7a:hover{
    8  color#66b1ff;
    9}
    10* {
    11  box-sizing: border-box;
    12}
    13
    14.container {
    15  width1080px;
    16  margin0 auto;
    17}
    18
    19input {
    20  background-color#fff;
    21  background-image: none;
    22  border-radius4px;
    23  border1px solid #dcdfe6;
    24  color#606266;
    25  display: inline-block;
    26  font-size: inherit;
    27  height40px;
    28  line-height40px;
    29  outline: none;
    30  padding0 15px;
    31  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
    32}
    33input:focus {
    34  outline: none;
    35  border-color#409eff;
    36}
    37
    38body {
    39  min-width1100px;
    40  line-height1.5;
    41  color#333;
    42}
    43
    44button {
    45  outline: none;
    46  border: none;
    47  width170px;
    48  font-size: inherit;
    49  color#fff;
    50  background-color#409eff;
    51  border-color#409eff;
    52  line-height1;
    53  white-space: nowrap;
    54  cursor: pointer;
    55  transition0.1s;
    56  font-weight500;
    57  font-size14px;
    58  border-radius4px;
    59  padding12px;
    60}
    61button:hover {
    62  background#66b1ff;
    63  border-color#66b1ff;
    64}

    全局导入

    main.js

     1// The Vue build version to load with the `import` command
    2// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    3import Vue from 'vue'
    4import "./assets/css/reset.css"
    5import "./assets/css/global.css"
    6import router from './router'
    7import store from "./store/index"
    8import Vuex from "vuex"
    9Vue.use(Vuex)
    10Vue.config.productionTip = false
    11
    12/* eslint-disable no-new */
    13new Vue({
    14  el'#app',
    15  router,
    16  store,
    17  components: {},
    18  template''
    19})

    2、在components/slider文件夹下新建Slider.vue和sliderIndex.vue这两个组件

    Slider.vue

     1<template>
    2    <div class="banner-container">
    3      <ul class="images">
    4        <li><a href=""><img src="../../assets/img/banner/banner1.jpeg" alt=""></a></li>
    5        <li><a href=""><img src="../../assets/img/banner/banner2.jpeg" alt=""></a></li>
    6        <li><a href=""><img src="../../assets/img/banner/banner3.jpeg" alt=""></a></li>
    7      </ul>
    8      <ul class="dots">
    9        <li class="active"></li>
    10        <li></li>
    11        <li></li>
    12      </ul>
    13    </div>
    14</template>
    15
    16<script>
    17    export default {
    18        name: "Slider",
    19    }
    20</script>
    21
    22<style scoped>
    23  /* 样式 */
    24  .banner-container {
    25    height: 350px;
    26    position: relative;
    27    overflow: hidden;
    28  }
    29  .banner-container li {
    30    display: block;
    31     1080px;
    32    height: 100%;
    33    float: left;
    34  }
    35  .images {
    36    height: 100%;
    37    transition: 0.5s;
    38  }
    39  .banner-container img {
    40     1080px;
    41    height: 100%;
    42  }
    43  .dots {
    44    position: absolute;
    45    bottom: 10px;
    46    right: 10px;
    47    display: flex;
    48  }
    49  .dots li {
    50     10px;
    51    cursor: pointer;
    52    height: 10px;
    53    margin: 0 3px;
    54    border-radius: 50%;
    55    border: 1px solid;
    56    color: #fff;
    57  }
    58  .dots li.active {
    59    background: #fff;
    60  }
    61</style>

    SliderIndex.vue

     1<template>
    2    <div style="1080px;margin: 0 auto ">
    3      <slider></slider>
    4    </div>
    5</template>
    6<script>
    7  import slider from "./Slider"
    8    export default {
    9        name: "SliderIndex",
    10        components:{
    11          slider:slider
    12        },
    13    }
    14</script>
    15
    16<style scoped>
    17
    18</style>

    这样,整体的布局效果就已经出来了。这里就不进行截图了。

    组件通信和静态资源导入

    在Slider.vue这个组件中,我们是将图片直接写死的,上面分析也提到过,哪些数据是可控的,哪些数据是不可控的,图片的话,我们动态引入。

    资源导入

    资源导入有两种方式,一种是import,另一种是require导入。

    • import 导入
    1  import banner1 from "../../assets/img/banner/banner1.jpeg"
    2  import banner2 from "../../assets/img/banner/banner2.jpeg"
    3  import banner3 from "../../assets/img/banner/banner3.jpeg"
    • require导入
    1require("./../../assets/img/banner/banner1.jpeg")
    2require("./../../assets/img/banner/banner2.jpeg")
    3require("./../../assets/img/banner/banner3.jpeg")

    这两种方式都可以,

    SliderIndex.vue

     1<template>
    2    <div style="1080px;margin: 0 auto ">
    3      <slider :sliderArray="sliderArray"></slider>
    4    </div>
    5</template>
    6<script>
    7  import slider from "./Slider"
    8  import banner1 from "../../assets/img/banner/banner1.jpeg"
    9  import banner2 from "../../assets/img/banner/banner2.jpeg"
    10  import banner3 from "../../assets/img/banner/banner3.jpeg"
    11    export default {
    12        name: "SliderIndex",
    13        components:{
    14          slider:slider
    15        },
    16        data(){
    17          return{
    18            sliderArray:[banner1,banner2,banner3]
    19          }
    20        }
    21    }
    22</script>
    23
    24<style scoped>
    25
    26</style>

    Slide.vue

     1<template>
    2    <div class="banner-container">
    3      <ul class="images">
    4        <li v-for="(item,i) of sliderArray" :key="i">
    5          <a href="javascript:void(0)"><img :src=item alt=""></a>
    6        </li>
    7      </ul>
    8      <ul class="dots">
    9        <li v-for="(item,i) of sliderArray" :key='i'></li>
    10      </ul>
    11    </div>
    12</template>
    13
    14<script>
    15    export default {
    16        name: "Slider",
    17      props:{
    18          sliderArray:{
    19            require:true,
    20            type:Array,
    21          }
    22      }
    23    }
    24</script>
    25
    26<style scoped>
    27  /* 样式 */
    28  .banner-container {
    29    height: 350px;
    30    position: relative;
    31    overflow: hidden;
    32  }
    33  .banner-container li {
    34    display: block;
    35     1080px;
    36    height: 100%;
    37    float: left;
    38  }
    39  .images {
    40    height: 100%;
    41    transition: 0.5s;
    42  }
    43  .banner-container img {
    44     1080px;
    45    height: 100%;
    46  }
    47  .dots {
    48    position: absolute;
    49    bottom: 10px;
    50    right: 10px;
    51    display: flex;
    52  }
    53  .dots li {
    54     10px;
    55    cursor: pointer;
    56    height: 10px;
    57    margin: 0 3px;
    58    border-radius: 50%;
    59    border: 1px solid;
    60    color: #fff;
    61  }
    62  .dots li.active {
    63    background: #fff;
    64  }
    65</style>

    到这一步的时候,有几个问题,第一个是默认我们图片显示第一张,小圆点默认第一个显示,容器的总宽度计算是总图片的长度*100%,Slide.vue定义内部数据index=0,当index和i相等时,添加active类

     1<template>
    2    <div class="banner-container">
    3      <ul class="images" :style="{
    4        sliderArray.length*100+'%',
    5        marginLeft:-index*100+'%'
    6      }">
    7        <li v-for="(item,i) of sliderArray" :key="i">
    8          <a href="javascript:void(0)"><img :src=item alt=""></a>
    9        </li>
    10      </ul>
    11      <ul class="dots">
    12        <li v-for="(item,i) of sliderArray" :class="{
    13          active:i===index
    14        }" :key="i"></li>
    15      </ul>
    16    </div>
    17</template>
    18
    19<script>
    20    export default {
    21        name: "Slider",
    22      props:{
    23          sliderArray:{
    24            require:true,
    25            type:Array,
    26          }
    27      },
    28      data(){
    29          return{
    30            index:0,
    31          }
    32      }
    33    }
    34</script>
    35
    36<style scoped>
    37  /* 样式 */
    38  .banner-container {
    39    height: 350px;
    40    position: relative;
    41    overflow: hidden;
    42  }
    43  .banner-container li {
    44    display: block;
    45     1080px;
    46    height: 100%;
    47    float: left;
    48  }
    49  .images {
    50    height: 100%;
    51    transition: 0.5s;
    52  }
    53  .banner-container img {
    54     1080px;
    55    height: 100%;
    56  }
    57  .dots {
    58    position: absolute;
    59    bottom: 10px;
    60    right: 10px;
    61    display: flex;
    62  }
    63  .dots li {
    64     10px;
    65    cursor: pointer;
    66    height: 10px;
    67    margin: 0 3px;
    68    border-radius: 50%;
    69    border: 1px solid;
    70    color: #fff;
    71  }
    72  .dots li.active {
    73    background: #fff;
    74  }
    75</style>

    这时,可以实现基本的轮播效果,在这里我们无需关注视图,只需要关注数据即可,因为数据改变了,视图之然就变了,可以用控制台改变index的值。

    小圆点切换时,图片切换

    这个功能的实现特别简单,只需要在点击的时候将i的值赋值给index即可,即index改变,视图重新渲染。

    1      <ul class="dots">
    2        <li v-for="(item,i) of sliderArray" :class="{
    3          active:i===index
    4        }" :key="i" @click="index=i"></li>
    5      </ul>

    自动轮播和停止轮播

    实现自动轮播的关键是在组件挂载时调用方法,停止轮播的关键是组件销毁时,销毁定时器。

    鼠标悬停,轮播停止。鼠标离开,录播继续。

     1<template>
    2    <div class="banner-container">
    3      <ul class="images" :style="{
    4        sliderArray.length*100+'%',
    5        marginLeft:-index*100+'%'
    6      }">
    7        <li v-for="(item,i) of sliderArray" :key="i" @mouseleave="autoStart" @mouseenter="autoStop">
    8          <a href="javascript:void(0)"><img :src=item alt=""></a>
    9        </li>
    10      </ul>
    11      <ul class="dots">
    12        <li v-for="(item,i) of sliderArray" :class="{
    13          active:i===index
    14        }" :key="i" @click="index=i"></li>
    15      </ul>
    16    </div>
    17</template>
    18
    19<script>
    20    export default {
    21        name: "Slider",
    22      props:{
    23          sliderArray:{
    24            require:true,
    25            type:Array,
    26          }
    27      },
    28      data(){
    29          return{
    30            index:0,
    31            timer:null
    32          }
    33      },
    34      mounted(){
    35        this.autoStart()
    36      },
    37      destroyed(){
    38          this.autoStop()
    39      },
    40      methods:{
    41          autoStart(){
    42            if(this.timer){
    43              return
    44            }
    45            this.timer=setInterval(()=>{
    46              this.index=(this.index+1)%this.sliderArray.length;
    47            },2000)
    48          },
    49          autoStop(){
    50            clearInterval(this.timer);
    51            this.timer=null;
    52          }
    53      }
    54    }
    55</script>
    56
    57<style scoped>
    58  /* 样式 */
    59  .banner-container {
    60    height: 350px;
    61    position: relative;
    62    overflow: hidden;
    63  }
    64  .banner-container li {
    65    display: block;
    66     1080px;
    67    height: 100%;
    68    float: left;
    69  }
    70  .images {
    71    height: 100%;
    72    transition: 0.5s;
    73  }
    74  .banner-container img {
    75     1080px;
    76    height: 100%;
    77  }
    78  .dots {
    79    position: absolute;
    80    bottom: 10px;
    81    right: 10px;
    82    display: flex;
    83  }
    84  .dots li {
    85     10px;
    86    cursor: pointer;
    87    height: 10px;
    88    margin: 0 3px;
    89    border-radius: 50%;
    90    border: 1px solid;
    91    color: #fff;
    92  }
    93  .dots li.active {
    94    background: #fff;
    95  }
    96</style>

    简单的轮播效果就已经实现了,整体难度不难,但是涉及的知识点比较多,从一个小的轮播效果就涉及那么多的知识点,所以说基础很重要,杨戬的基础也不是很好,但是杨戬是一个喜欢学习的暖男(我信你个鬼),好了,看到这里,本编博客的内容就要结束了,我们下篇文章见。

    结尾

    如果觉得本篇文章对您有用的话,可以麻烦您帮忙点亮那个点赞按钮吗?

    对于杨戬这个暖男来说:真的真的非常有用,您的支持将是我继续写文章前进的动力,我们下篇文章见。

    【原创】|二郎神杨戬

    二郎神杨戬,一个在互联网前端苟且偷生的划水程序员,专注于前端开发,善于技术分享。
    如需转载,请联系作者或者保留原文链接,微信公众号搜索二郎神杨戬或者扫描下方的二维码更加方便。

    一起来见证二郎神杨戬的成长吧!更多好文、技术分享尽在下方这个公众号。欢迎关注。

  • 相关阅读:
    虚方法的调用是怎么实现的(单继承VS多继承)
    C++ Data Member内存布局
    删除单链表,你会吗?
    最近面试遇到的Windows相关的题目
    C# 文章导航
    移动端开发文章导航
    Vue源码阅读(一) 准备工作
    vue-router源码阅读(一) 内部探究
    Vuex源码阅读(二) store内的getters实现逻辑
    Vuex源码阅读(一) new Vuex.Store()内部探究
  • 原文地址:https://www.cnblogs.com/jjgw/p/13322931.html
Copyright © 2011-2022 走看看