目录

关于template外壳:

关于图片的自动切换的处理:

为什么要把第一张图片外的 li 克隆一份放到 li 列表的最后:

函数节流处理 :


关于template外壳

创建一个div,用于内容的呈现,溢出的内容设置为隐藏;

div下创建一个内外边距都为0px的ul,ul的高与div一致,宽为(所要展现图片数+1)* (div的宽),(注:加1是因为将克隆第一张图片并放到最后,完善切换效果更);

ul下创建一个list-style为none的li,设置li的宽高跟外部的div大小一样,li包裹一个img,img的宽高拉满,铺满div。用v-for遍历存放在data中的图片数组pictures,生成多个li、img,设置li向左浮动,这样多张图片就能并排排列在一行上展示。可以取消div隐藏溢出内容的属性,这样便于观察和调试。

在div区域内的左侧和右侧分别创建一个img,分别展示向左向右的小图片,用户点击相应的小图片,则执行相应的切换。div的底部设置一行并排的小圆,存在唯一一个填充项并跟随图片的切换而切换,用实时唯一填充项指示当前所展示的图片的信息,当用户点击未被填充的小圆圈时,将自动切换展示指定的图片。

当用户操作鼠标在div范围内活动时,左右两侧小图标以及底部的圆圈图标将显现(v-show),并且可以点击(背景图片也可以点击,所以整个最外侧的div区域以内都是可点击区域),鼠标样式变为pointer。

轮播图组件<template></template>中的内容:

<template><!-- 最外层div --><div class="outest" @mouseover="mouseEnter = true" @mouseleave="mouseEnter = false" ><!-- 向左img --><img class="icon _left" src="../img/向左.png" alt="向左" v-show="mouseEnter" @click="gotoLast()"/><!-- 主要图片 --><ul ref="myul"><li v-for="e of pictures" :key="e.index" :ref="e.ref"><img :src="e.src" :alt="e.alt" /></li></ul><!-- 底部小圆圈的设置 --><div class="mydiv" v-show="mouseEnter"><div class="empty-cicle" v-for="e of pictures" :key="e.index" ref="cicle" @click="gotoDirectly(e.index)" ></div></div><!-- 向右div --><img class="icon _right" src="../img/向右.png" alt="向右" v-show="mouseEnter" @click="gotoNext()"/></div>
</template>

css: 

<style scoped>.outest {width: 600px;height: 400px;border: 2px rgb(115, 170, 243) solid;border-radius: 5px;padding: 0px;position: absolute;overflow: hidden;cursor: pointer;background-color: bisque;}/** 轮播图片设置 */ul {margin: 0px;padding: 0px;width: calc(6 * 100%);height: 100%;}ul > li {width: calc(1 / 6 * 100%);height: 100%;list-style: none;float: left;}li > img {width: 100%;height: 100%;}/* 左右图标设置 */.icon {width: 30px;height: 60px;position: absolute;top: 170px;z-index: 2;opacity: 0.5;}._left {left: 0px;}._right {right: 0px;}/* 底部小圆圈的设置 */.mydiv {width: auto;height: 30px;display: inline-block;position: absolute;bottom: 0px;left: 250px;z-index: 5;opacity: 0.5;}.empty-cicle {display: inline-block;width: 10px;height: 10px;border: 2px solid black;border-radius: 90px;z-index: 5;margin-right: 5px;}
</style>

关于图片的自动切换的处理:

首先是当页面加载完毕后,要让图片的切换能自动进行。根据以上的html以及css配置,ul下每个li都位于一行显示,彼此紧凑,这样可以通过移动ul的绝对位置来改变最外层div(outest)中呈现的图片内容。先设置outset为绝对定位,然后在mounted中通过ref拿到dom来修改行内样式style,设置ul也为绝对定位,距离左侧为0px。后续将通过this.$refs.myul.style.offsetLeft获取myul左侧距离outset左侧的距离,通过改变this.$refs.myul.style.left来修改整个ul的位置,以实现图片过渡变换和改变呈现的图片。

可以在mounted配置对象中给window添加一个 一个自定义属性timer,然后赋一个定时器setInterval给他,让页面挂载完毕就开始执行定时器,定时器setInterval经过指定的时间自动执行,可以用于经过指定时间后自动切换图片。该定时器的回调函数中再嵌套一个setInterval,这个定时器则用来缓慢过渡到下一张图片。当用户操作鼠标进入到当前组件区域,可以触发一个自定义事件,清除定时器timer,让图片的变换停止。

我用了另外一种方式,在main.js文件 创建vm前给vm添加了一个自定义属性$mytimer,在组件文件中data设置一个属性mouseEnter,值为布尔值,当鼠标在组件区域内活动时改变其值为true,反之为false。并在watch中对它进行监视,开启立即监视immediate:true,立即监视使第一次执行handler()处理函数的时间在mounted之前,这样,当handler收到的第一个参数为false,将一个自动切换图片的定时器setInterval赋给$mytimer,这样页面一挂载就能自动执行图片的切换,并且每次鼠标离开后都会重新生成同样的定时器来切换图片。当handler收到的第一个参数为true时,清除$mytimer绑定的定时器。

main.js文件内容:

import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falsenew Vue({render: h => h(App),beforeCreate(){Vue.prototype.$mytimer=null}
}).$mount('#app')

data中的数据(五张图片均来源于网络) :

    data() {return {pictures: [{src: "https://img0.baidu.com/it/u=1491296277,1329539836&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500",alt: "撸起袖子加油干",index: "0",ref: "picture",},{src: "https://img2.baidu.com/it/u=141235511,288522525&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=263",alt: "植树造林",index: "1",ref: "picture",},{src: "https://img1.baidu.com/it/u=2564747122,3162867613&fm=253&fmt=auto&app=138&f=JPEG?w=888&h=500",alt: "疫情防控常态化",index: "2",ref: "picture",},{src: "https://img1.baidu.com/it/u=1221896196,2147882061&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=250",alt: "1FCA0F23.png戴头盔",index: "3",ref: "picture",},{src: "https://img1.baidu.com/it/u=3117634844,2583644829&fm=253&fmt=auto&app=138&f=JPEG?w=1024&h=492",alt: "培育文明之魂",index: "4",ref: "picture",},],mouseEnter: false,      //鼠标是否悬浮在整个区域上pictureShowing: 0,      //当前展示的是第几张图片,用来更新底部圆点hasClicked:false,       //函数节流,防止用户快速、频繁点击图片变换导致出错,flase为图片变换操作不可执行};},

watch: 

    watch: {mouseEnter: {                           //鼠标移入区域,图片切换停止,离开则继续immediate: true,handler(newval, oldval) {           //使其在页面一上来就能执行if (!newval) {     this.$mytimer = setInterval(() => {if (this.pictureShowing < this.pictures.length-1) {this.pictureShowing++;} else {this.pictureShowing = 0;}this.changeDefault(10);}, 3000);} else {clearInterval(this.$mytimer);}},},pictureShowing(newval) {                //当改变图片时,更新底部小圆圈for (let i = 0; i < this.pictures.length; i++) {(this.$refs.cicle)[i].style.background = "";}(this.$refs.cicle)[newval].style.background = "black";},},

mounted: 

    mounted() {// console.log(this.$refs[`picture`])          //是一个 Array 包含 5 个 li 元素// 解决当前页面被最小化后,用户再打开时,轮播图播放情况出现异常的情况// 监视浏览器窗口的改变,当浏览器窗口最小化时,将默认定时器停掉,当浏览器可视时,再开启document.addEventListener('visibilitychange',()=>{          if(document.visibilityState === 'hidden'){clearInterval(this.$mytimer);}else if(document.visibilityState === 'visible'){this.$mytimer= setInterval(() => {if (this.pictureShowing < this.pictures.length-1) {this.pictureShowing++;} else {this.pictureShowing = 0;}this.changeDefault(10);}, 3000);}})let li_0 = this.$refs[`picture`][0];let li_end = li_0.cloneNode(true);this.$refs.myul.appendChild(li_end);            //克隆第一张图片,加到ul最后展示的位置this.$refs.myul.style.position = "absolute";this.$refs.myul.style.left = 0 + "px";this.$refs.cicle[0].style.background = "black";    //挂载时展示第一张图片,默认第一个圆圈被填充},

为什么要把第一张图片外的 li 克隆一份放到 li 列表的最后:

(底部小圆圈也是通过遍历data中的pictures生成的,数量跟实际图片的个数一致,克隆出来放在最后的图片不会使圆圈个数增加)

整个轮播图设计下一张图片从右向左出现,上一张图片也从右向左隐藏(就像下一张图片从outest的右侧出来,把上一张图片从outest左侧挤走)。

根据当前组件的配置,以原始5张图片没有第六张克隆图片为例,当outest正在展示第五张图片,即将要自右向左退出outest区域进行隐藏时,如果ul整体往左移动,因为第五张往右就没有图片了,ul的宽度又恰好是五张图片的距离,此时右侧就会逐渐显示为空白(如果outest没有设置背景);如果说要在第五张向第一张过渡时,瞬间将ul的left设置为600(ul左侧距离outest区域左侧一个outset的宽度),让第一张图片自右往左显现,那么用户还是能看见左侧区域的空白(或outest的背景)。如果就把outest的背景就设置为第五张图片,并且采取上述的第二种方式,或许也能完成吧(快写完的时候想到的。。)。

克隆第一张图片的li,放到ul中li列表的末尾,主要为了解决的上述的第一种情况。当轮播到第五张图片,第五张图片即将要向左退出隐藏,因为第六张图片是第一张图片的克隆,所以第六张图片自右往左显现解决了原本第五张图片向第六张图片过渡的问题,当第六张图片恰好完全显示的瞬间,将ul的left设置为0px,将outest所展示的图片在刹那间替换为第一张,这样又回到了ul列表初始展示的位置,同时也解决了ul继续左移的问题。

methods:

    methods: {changeDefault(speed) {                  //切换下一张图片    speed为每毫秒移动的距离let t = 0;                          //根据每秒移动的位移控制单次位移结束let timer = setInterval(() => {t++;this.$refs.myul.style.left = this.$refs.myul.offsetLeft - Number(speed) + "px";if (t === 600/speed) {if(this.$refs.myul.offsetLeft===-3000){             //当最后一张图片(第一张的克隆)刚好完全展示时回到第一张完全展示时的位置this.$refs.myul.style.left=0+"px";}clearInterval(timer);this.hasClicked=false;}}, 1);},quickTurn(count,index) {              //count为用户点击的点与当前 被填充点 的距离let currentX = this.$refs.myul.offsetLeft;let t = setInterval(() => {this.$refs.myul.style.left = this.$refs.myul.offsetLeft - count * 20 + "px";if (this.$refs.myul.offsetLeft === currentX - 600 * count) {if(index===0){this.$refs.myul.style.left=0+"px";}clearInterval(t);this.hasClicked=false;}}, 1);},gotoPicture(index) {let id = Number(index);let showing = this.pictureShowing;if (id === showing) {return null;} else {this.quickTurn(index - showing,index);this.pictureShowing = index;}},gotoLast(){             //上一张if(this.hasClicked){return null;}this.hasClicked=true;if(Number(this.pictureShowing)===0){this.$refs.myul.style.left=-3000+"px";this.pictureShowing=this.pictures.length-1;this.quickTurn(-1,this.pictureShowing);}else{this.gotoPicture(this.pictureShowing-1);}},gotoNext(){             //下一张if(this.hasClicked){return null;}this.hasClicked=true;if(Number(this.pictureShowing)===this.pictures.length-1){this.changeDefault(20);this.pictureShowing=0;}else{this.gotoPicture(this.pictureShowing+1)}},gotoDirectly(index){    //跳到某一张if(this.hasClicked){return null;}this.hasClicked=true;this.gotoPicture(index);}},

函数节流处理 :

在data中定义的hasClicked,其值为布尔值,用于判断是否有定时器即将开始执行或正在执行。

为了防止用户快速地点击outset两侧的img或频繁更换点击底部的小圆而频频触发定时器,在左右的img和底部的小圆圈被点击时分别触发的函数gotoLast()、gotoNext()、gotoDirectly()中的开头都添加了一个判断,如果当前仍在执行上一个由gotoLast、gotoNext或gotoDirectly生成的定时器setInterval时(即this.hasClicked为true),则结束当前的函数进程(即当有定时器正在工作,则在此期间无法再触发函数以改变ul的位置)。当任意一个定时器运行结束时,将hasClicked设置为false,可以执行下一个触发定时器的操作。

学习使用vue实现一个简单的轮播图相关推荐

  1. 制作一个简单的轮播图(详解新手教学)

    制作一个简单的轮播图(详解新手教学) 相信很多初学者,无论是前端还是后端,对于制作页面时,都想自己亲手制作一个轮播图. 如何制作一个轮播图: 基础知识:有HTML,Css,js基础 本文使用技术: H ...

  2. 制作一个简单的轮播图

    记录一下轮播图制作(这里用的是原生js制作的) 前期准备工作 1.自己用的顺手的开发工具,我这里用的时HBuilder来写的 2.创建项目 3.在项目中创建images.css.js文件夹,把需要制作 ...

  3. jquery手写轮播图_用jQuery如何手写一个简单的轮播图?(附代码)

    用jQuery如何手写一个简单的轮播图?下面本篇文章通过代码示例来给大家介绍一下.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 用 jQuery 手写轮播图 先上个效果截图: 主要 ...

  4. 使用jQuery,写一个简单的轮播图,实现切换功能!

    1.谈到jquery,想必大家都知道,它是一个js库.使用起来简单又方便,接下来就给大家看看我用jquery实现的轮播图吧! <!DOCTYPE html> <html lang=& ...

  5. 原生js实现一个简单的轮播图

    想锻炼一下自己的原生js能力可以从写一个轮播图开始,轮播图的运用想必大家都知道吧,好了废话不多说,开始记笔记了,一些需要注意的点,我都在代码中标注了 首先是构造html: <div id=&qu ...

  6. 使用jQuery写一个简单的轮播图(笔记)

    html代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  7. jQuery实现一个简单的轮播图

    一.轮播图内容组成 包括:4张图片,图片标号,向左翻页,向右翻页的几个部分,如下图所示: 二.实现功能 1.加载页面后,4张图片默认从第一张图片开始轮播,索引值为1. 2.当把鼠标over到图片上时, ...

  8. swiper怎么在HTML引入JS文件,Swiper.js插件超简单实现轮播图

    Swiper是纯javascript打造的滑动特效插件,面向手机.平板电脑等移动终端.能实现触屏焦点图.触屏Tab切换.触屏多图切换等常用效果.超好用 话不多说,直接上教程 1.首先加载插件,需要用到 ...

  9. 微信小程序最简单的轮播图

    小程序轮播图 今天给大家分享一个在微信开发者工具开发微信小程序的简单案例--轮播图(只用wxml和wxss) 话不多说,直接上代码!!! 效果图 WXML代码 基本属性介绍 <!-- indic ...

最新文章

  1. Win或Linux系统下用conda安装Open Babel
  2. 12c oracle 修改内存_Oracle12c中性能优化功能增强新特性之重大突破——内存列存储新特性...
  3. norm--求矩阵和向量的范数
  4. PAT甲级1113 Integer Set Partition:[C++题解]贪心
  5. 关于微信小程序使用wx.downloadFile和wx.getFileSystemManager().saveFile()保存文件在本机找不到文件的说明
  6. 5大过程组与整体管理
  7. python enumeration_python枚举防止无效的属性分配
  8. 四款机型全面开售 海蓝色iPhone 12 Pro最受欢迎
  9. Java语言之Integer类
  10. RetinaFace论文解读 --- RetinaFace: Single-stage Dense Face Localisation in the Wild
  11. 汇率兑换 python第一课_【Python 07】汇率兑换1.0-2(基本元素)
  12. [APIO2014]连珠线 题解
  13. STL源码剖析(一)STL简介
  14. 1.MATLAB图像处理基础知识
  15. 设计模式学习笔记(C++实现)(七)--适配器模式
  16. Hibernate_day01
  17. (五)统计分析基本算法
  18. docker CPU限制参数
  19. 学生硬件电路设计经验教训浅谈
  20. 利用D415读取 需要标记的人脸face_recognition的距离 Python + wind10

热门文章

  1. Element table各种合并单元格
  2. 软考2022下半年上午题真题和知识点整理
  3. Java系统插件开发原理与实例
  4. 网站运维:git工具(10):GitLab安装和使用
  5. super this
  6. 关于K.im的满满干货!
  7. Java基础面试题(2012完整版)
  8. 有哪位仁兄可以告诉我,下载软件包的时候出现这种情况是怎么一回事呢?kali虚拟机,希望看见的前辈不吝赐教
  9. ios根据服务器修改App名称,iOS 修改APP 名称
  10. 【WPS】WPS之如何给文件加密?