1.前言

vue用了有一段时间了,开发的后台管理系统也趋于完善,现在时间比较算是有点空闲吧!这个空闲时间我在研究vue的另外的一些玩法,比如组件,插件等。今天,我就分享一个组件的练手项目--焦点图切换组件。这个项目是我用于vue组件练习的一个项目,当然了,代码也会提交到github(ec-slider),也会维护。我也想我开发的东西好用一点!现在,就是建议有需要的伙伴,可以来玩下这个项目,当练习的作用!另外,如果大家有什么建议,欢迎指点!

建议
1.下面的步骤,最好在自己本地上跑起来,根据文章的步骤,逐步完成,如果只看代码,很容易懵逼的。
2.如果不清楚哪个代码有什么作用,可能自己调试下,把代码去掉后,看下有什么影响,就很容易想出代码有什么作用了!

2.项目目录

很普通,很好理解的一个目录,但还是简单的解释一下吧

node_modules:文件依赖模块(自动生成)
dist:打包文件产出目录(自动生成)
src:开发文件目录
src/components:组件文件目录
.babelrc:babel编译es6的配置文件
.gitnore:不提交到git的文件(目录)的配置文件
fontSize:设置rem算法的文件(现在没用到,忽略)
index.html:模板文件
index.js:入口文件
package.json:配置文件
README.md:说明文档
webpack.config.babel.js:webpack配置文件

3.步骤详解

3-1跑起来

这是项目的第一步(项目搭建这个,我不多说,之前的文章已经说了几次了!),现在src/components/ec-slider.vue这里输出一个‘守候’
1.首先,在src/components/ec-slider.vue里面输出‘守候’,代码如下

  1. <template>
  2. <div>
  3. 守候
  4. </div>
  5. </template>
  6. <script type="text/javascript">
  7. export default {
  8. data () {
  9. return {
  10. }
  11. },
  12. computed: {
  13. },
  14. mounted(){
  15. },
  16. props: [],
  17. methods: {
  18. }
  19. }
  20. </script>

2.然后,在src/components/index.js里面设置注册组件(要带一个install方法),代码如下

  1. import SlideImg from './ec-slider.vue'
  2. const ecslide={
  3. install:function (Vue) {
  4. Vue.component('ec-slide',SlideImg)
  5. }
  6. }
  7. export default ecslide;

3.在入口文件,index.js里面引入并且使用组件

  1. require("./index.html");
  2. require("./src/sass/index.scss");
  3. import Vue from 'vue'
  4. //引入并且使用组件
  5. import ecslide from './src/js/components/index';
  6. Vue.use(ecslide);
  7. let app6 = new Vue({
  8. el: "#app6",
  9. data: {
  10. },
  11. mounted(){
  12. }
  13. });

4.在index.html(模板文件),输出组件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  6. <title>Title</title>
  7. </head>
  8. <body>
  9. <div id="app6">
  10. <ec-slide></ec-slide>
  11. </div>
  12. </body>
  13. </html>

5.命令行输入$ npm run dev跑起来,结果完美!这几步的原理貌似没什么可多说的,都是固定式的步骤。

3-2开发准备

经过上一步之后,基础就已经打好了,那么接下来就是一个开发的过程,大部分都是修改src/components/ec-slider.vue这个文件。
开发之前,大家不要急着写代码,先分析下当中的运行流程!
首先,一个焦点图切换,需要什么参数?根据下面的一个淘宝栗子,我简单分析下,就是下面这几个!

list-图片列表[{src:'url',href:'https://www.baidu.com'},{src:'url',href:'http://www.163.com'}](src:图片的src,href:跳转连接,点击图片的时候)
autoplay-是否自动播放 布尔 (默认false)
type-轮播方式‘transparent’(透明度切换), 'slide'(滑动切换) (默认slide)
option-对应切换 (默认false,不显示)
time-轮播间隔时间,毫秒 (默认4000)
sildetype-过渡效果 (默认'ease'慢速开始,然后变快,然后慢速结束的过渡效果,参考:transition-timing-function
arrowurl-箭头图片链接
arrowsize-箭头尺寸‘width,height’
direction-切换方向'left'(左右) 'top'(上下) (默认:左右)

分析完了之后,就知道暂时需要这么多参数,那么接下来就是在ec-slider.vue里面,接收这些参数。父子组件传参方式,我想大家知道--props。代码如下

  1. <template>
  2. <div>
  3. 守候
  4. </div>
  5. </template>
  6. <script type="text/javascript">
  7. export default {
  8. data () {
  9. return {
  10. }
  11. },
  12. computed: {
  13. },
  14. mounted(){
  15. },
  16. props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl','arrowsize','option','direction'],
  17. methods: {
  18. }
  19. }
  20. </script>

有地方接收参数,肯定要有地方传参数,就是index.html模板文件里面传

  1. <div class="slider-left">
  2. <ec-slide :list='list' :autoplay="true" :type="'slide'" :option="true" :time="4000" :sildetype="'ease'" :arrowurl="'http://i1.buimg.com/1949/4d860a3067fab23b.jpg'" :arrowsize="'20,40'" :direction="'left'"></ec-slide>
  3. </div>

3-3样式布局

既然知道了,会接收什么参数,那下面先把样式布局,给弄好先,这个不多说,代码如下!(有些解释我也是直接打到代码上)

  1. <template>
  2. <div class="switch-img-box" id="ec-slide-box">
  3. <div class="switch-img-type switch-img-left">
  4. <ul :style="{'width':ulWidth,'transition-timing-function':slideChange}">
  5. <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}">
  6. <a :href="li.href?li.href:'javascript:;'">
  7. <img :src="li.src" class="slider-img"/>
  8. </a>
  9. </li>
  10. </ul>
  11. </div>
  12. <!--如果需要显示对应的点-->
  13. <div class="switch-option" v-if="option">
  14. <div>
  15. <span v-for="(li,index) in list"></span>
  16. </div>
  17. </div>
  18. <!--如果需要显示箭头-->
  19. <div class="switch-arrow" v-if="arrowurl&&arrowsize">
  20. <div :class="{'arrow-left':direction==='left','arrow-top':direction==='top'}"
  21. :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}"></div>
  22. <div :class="{'arrow-right':direction==='left','arrow-bottom':direction==='top'}"
  23. :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}"></div>
  24. </div>
  25. </div>
  26. </template>
  27. <script type="text/javascript">
  28. export default {
  29. data () {
  30. return {
  31. slideChange: '',
  32. arrowWidth: '',
  33. arrowHeight: '',
  34. }
  35. },
  36. computed: {
  37. //ul宽度
  38. ulWidth: function () {
  39. return (this.list.length) + "00%";
  40. },
  41. //li宽度
  42. listWidth: function () {
  43. return 100 / (this.list.length)
  44. }
  45. },
  46. mounted(){
  47. //设置各个数据初始值
  48. this.slideChange = this.sildetype || 'ease';
  49. if (this.arrowsize && this.arrowurl) {
  50. this.arrowWidth = this.arrowsize.split(',')[0];
  51. this.arrowHeight = this.arrowsize.split(',')[1];
  52. }
  53. },
  54. props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl', 'arrowsize', 'option', 'direction'],
  55. methods: {
  56. }
  57. }
  58. </script>
  59. <style lang="scss">
  60. .ec-slide-img-box {
  61. width: 100%;
  62. height: 100%;
  63. position: relative;
  64. touch-action: none;
  65. }
  66. .ec-slide-img-type {
  67. position: relative;
  68. overflow: hidden;
  69. width: 100%;
  70. height: 100%;
  71. &.ec-slide-img-top {
  72. }
  73. &.ec-slide-img-left {
  74. li {
  75. display: inline-block;
  76. font-size: 0;
  77. }
  78. }
  79. &.ec-slide-img-transparent {
  80. li {
  81. opacity: 0;
  82. transition: opacity 1s;
  83. width: 0;
  84. &.cur {
  85. width: auto;
  86. }
  87. &.show {
  88. opacity: 1;
  89. }
  90. }
  91. }
  92. ul {
  93. font-size: 0;
  94. &.tran {
  95. transition: all .4s;
  96. }
  97. li {
  98. text-align: center;
  99. }
  100. img {
  101. vertical-align: middle;
  102. max-width: 100%;
  103. max-height: 100%;
  104. }
  105. }
  106. }
  107. .ec-slide-arrow {
  108. div {
  109. position: absolute;
  110. z-index: 2;
  111. margin: auto;
  112. top: 0;
  113. bottom: 0;
  114. right: 0;
  115. left: 0;
  116. opacity: .5;
  117. &:hover {
  118. opacity: 1;
  119. }
  120. &.arrow-left {
  121. left: 10px;
  122. right: auto;
  123. }
  124. &.arrow-right {
  125. right: 10px;
  126. left: auto;
  127. transform: rotate(180deg);
  128. }
  129. &.arrow-top {
  130. top: 10px;
  131. bottom: auto;
  132. }
  133. &.arrow-bottom {
  134. bottom: 10px;
  135. top: auto;
  136. transform: rotate(180deg);
  137. }
  138. }
  139. }
  140. .ec-slide-option {
  141. position: absolute;
  142. font-size: 0;
  143. bottom: 10px;
  144. text-align: center;
  145. width: 100%;
  146. z-index: 5;
  147. &.isFirst {
  148. span:first-child {
  149. display: none;
  150. }
  151. }
  152. &.isLast {
  153. span:last-child {
  154. display: none;
  155. }
  156. }
  157. span {
  158. border-radius: 100%;
  159. margin: 0 5px;
  160. background: #fff;
  161. display: inline-block;
  162. width: 10px;
  163. height: 10px;
  164. &.active {
  165. background: #09f;
  166. }
  167. }
  168. &.ec-slide-option-top {
  169. display: table;
  170. width: 10px;
  171. height: 100%;
  172. top: 0;
  173. right: 10px;
  174. margin: auto;
  175. bottom: 0;
  176. span {
  177. margin: 5px 0;
  178. }
  179. div {
  180. display: table-cell;
  181. vertical-align: middle;
  182. }
  183. }
  184. }
  185. </style>

运行结果,就是下面这样

3-4执行动画

布局搞定了,下面就可以写动画,让轮播动起来!这里也需要增加几个变量,一个是nowIndex,记录当前索引。一个是timer定时器!
首先,我用transform:translate3d()这个方式控制ul的滑动。

  1. <ul :style="{'width':ulWidth,'transform':'translate3d(-'+(listWidth*(nowIndex))+'%,0,0)','transition-timing-function':slideChange,'transition': 'all .4s'}">
  2. <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}">
  3. <a :href="li.href?li.href:'javascript:;'">
  4. <img :src="li.src" class="slider-img"/>
  5. </a>
  6. </li>
  7. </ul>

然后,根据nowIndex,设置对应点的class。

  1. <div class="switch-option" v-if="option">
  2. <div>
  3. <!--如果当前索引index等于nowIndex。则添加active这个class,点就会变成蓝色-->
  4. <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span>
  5. </div>
  6. </div>

js代码如下

  1. <script type="text/javascript">
  2. export default {
  3. data () {
  4. return {
  5. nowIndex: 0,
  6. timer: null,
  7. slideChange: '',
  8. arrowWidth: '',
  9. arrowHeight: '',
  10. }
  11. },
  12. computed: {
  13. //ul宽度
  14. ulWidth: function () {
  15. return (this.list.length) + "00%";
  16. },
  17. //li宽度
  18. listWidth: function () {
  19. return 100 / (this.list.length)
  20. }
  21. },
  22. mounted(){
  23. //是否自动播放
  24. if (this.autoplay) {
  25. this.autoSwitch();
  26. }
  27. //设置初始值
  28. this.slideChange = this.sildetype || 'ease';
  29. if (this.arrowsize && this.arrowurl) {
  30. this.arrowWidth = this.arrowsize.split(',')[0];
  31. this.arrowHeight = this.arrowsize.split(',')[1];
  32. }
  33. },
  34. props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl', 'arrowsize', 'option', 'direction'],
  35. methods: {
  36. //滑动操作
  37. switchDo(reduce){
  38. clearInterval(this.timer);
  39. //根据reduce判断this.nowIndex的增加或者减少!
  40. //如果是减少模式reduce=‘reduce’
  41. if (reduce === 'reduce') {
  42. //如果nowIndex等于0,已经是第一个了,就回到最后一个
  43. if (this.nowIndex === 0) {
  44. this.nowIndex = this.list.length - 1;
  45. }
  46. else {
  47. this.nowIndex--;
  48. }
  49. }
  50. //如果是增加模式reduce=undefined
  51. else {
  52. //如果nowIndex等于this.list.length-1,已经是最后一个了,就回到第一个
  53. if (this.nowIndex === this.list.length-1) {
  54. this.nowIndex = 0;
  55. }
  56. else{
  57. this.nowIndex++;
  58. }
  59. }
  60. //如果需要自动播放
  61. if (this.autoplay) {
  62. this.autoSwitch();
  63. }
  64. },
  65. //自动播放函数
  66. autoSwitch(){
  67. let time = this.time || 4000;
  68. this.timer = setInterval(() => {
  69. this.switchDo();
  70. }, time);
  71. }
  72. }
  73. }
  74. </script>

到了这里,剩下的就只有点击两个箭头,执行相应动画,这个就相对简单,无非就是调用switchDo函数,唯一区别在于,点击左边的箭头,是减少模式,右边箭头的增加模式。代码如下,很好理解。

  1. <!--判断是否需要显示箭头-->
  2. <div class="switch-arrow" v-if="arrowurl&&arrowsize">
  3. <div :class="{'arrow-left':direction==='left','arrow-top':direction==='top'}"
  4. :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo('reduce')"></div>
  5. <div :class="{'arrow-right':direction==='left','arrow-bottom':direction==='top'}"
  6. :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo"></div>
  7. </div>

到了这里,对交互有强迫症的开发者就受不了了,到了最后一张,再点击右边箭头,就会出现下面的情况!

到了第一张,再点击左边箭头也是类似的情况,这样就很不好。理想情况是下面这样

3-5细节优化

要想做上面的效果,改的地方会比较多,先说下原理吧,到了最后一张,这个时候,再点击右边箭头,像淘宝那样,回到第一张。到了第一张,再点击左边箭头类似效果回到最后一张。那么最后的布局是这样

这样布局能实现效果,到了最后一张,这个时候,再点击右边箭头,像淘宝那样,回到第一张。就像下面

这个时候,就需要多做一步,滚动到这里的时候,瞬间拉回去。而且这个拉回去,要把ul的过渡效果transition去掉,不然就会看到拉回去的过渡效果!同时要改变nowIndex。

1.首先,ul布局方面

  1. <div class="switch-img-type switch-img-left" v-if="type==='slide'&&direction==='left'">
  2. <!--用tran这个class控制ul是否含有过渡效果,样式已经写好-->
  3. <ul :style="{'width':ulWidth,'transform':'translate3d(-'+(listWidth*(nowIndex+1))+'%,0,0)','transition-timing-function':slideChange}"
  4. :class="{'tran':noLast}">
  5. <!--最后一张图片-->
  6. <li :style="{'width':listWidth+'%'}">
  7. <a :href="list[list.length-1].href?list[list.length-1].href:'javascript:;'">
  8. <img :src="list[list.length-1].src" class="slider-img"/>
  9. </a>
  10. </li>
  11. <!--遍历出来的图片-->
  12. <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}">
  13. <a :href="li.href?li.href:'javascript:;'">
  14. <img :src="li.src" class="slider-img"/>
  15. </a>
  16. </li>
  17. <!--第一张图片-->
  18. <li :style="{'width':listWidth+'%'}">
  19. <a :href="list[0].href?list[0].href:'javascript:;'">
  20. <img :src="list[0].src" class="slider-img"/>
  21. </a>
  22. </li>
  23. </ul>
  24. </div>

2.然后,对应的点修改

  1. <!--isLast:隐藏最后一个span,isFirst隐藏第一个span-->
  2. <div class="switch-option" v-if="option"
  3. :class="{'isLast':nowIndex===list.length, 'isFirst':nowIndex===-1,'switch-option-top':direction==='top'}">
  4. <div>
  5. <span class="active span1" v-if="nowIndex===list.length"></span>
  6. <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span>
  7. <span class="active span2" v-if="nowIndex===-1"></span>
  8. </div>
  9. </div>

这个可能会有点绕,我解释下,比如滚动最后一张了,再点击右边箭头,向右滑动到第一张的时候,如下图

这个时候又要把第一个点变成蓝色,但是对应点的索引和nowIndex对不上,这个时候用一个技巧。把第一个(.span1)点显示出来,然后把最后一个点隐藏。这样还是用户看到还是看到4个点在屏幕!等动画执行完了,拉回去第一张的时候。把.span1隐藏,正常显示对应的点!这个大家细想一下就知道了。到了第一张,再点击左边箭头类似效果回到最后一张也是相同的处理方式!

到这里,功能就基本完成了,下面给出这部分代码!

  1. <template>
  2. <div class="ec-slide-img-box" id="ec-slide-box">
  3. <div class="ec-slide-img-type ec-slide-img-left" v-if="type==='slide'&&direction==='left'">
  4. <!--用tran这个class控制ul是否含有过渡效果,样式已经写好-->
  5. <ul :style="{'width':ulWidth,'transform':'translate3d(-'+(listWidth*(nowIndex+1))+'%,0,0)','transition-timing-function':slideChange}"
  6. :class="{'tran':noLast}">
  7. <!--最后一张图片-->
  8. <li :style="{'width':listWidth+'%'}">
  9. <a :href="list[list.length-1].href?list[list.length-1].href:'javascript:;'">
  10. <img :src="list[list.length-1].src" class="slider-img"/>
  11. </a>
  12. </li>
  13. <!--遍历出来的图片-->
  14. <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}">
  15. <a :href="li.href?li.href:'javascript:;'">
  16. <img :src="li.src" class="slider-img"/>
  17. </a>
  18. </li>
  19. <!--第一张图片-->
  20. <li :style="{'width':listWidth+'%'}">
  21. <a :href="list[0].href?list[0].href:'javascript:;'">
  22. <img :src="list[0].src" class="slider-img"/>
  23. </a>
  24. </li>
  25. </ul>
  26. </div>
  27. <!--isLast:隐藏最后一个span,isFirst隐藏第一个span-->
  28. <div class="ec-slide-option" v-if="option"
  29. :class="{'isLast':nowIndex===list.length, 'isFirst':nowIndex===-1,'ec-slide-option-top':direction==='top'}">
  30. <div>
  31. <span class="active" v-if="nowIndex===list.length"></span>
  32. <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span>
  33. <span class="active" v-if="nowIndex===-1"></span>
  34. </div>
  35. </div>
  36. <div class="ec-slide-arrow" v-if="arrowurl&&arrowsize">
  37. <div :class="{'arrow-left':direction==='left','arrow-top':direction==='top'}"
  38. :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}"
  39. @click.stop="switchDo('reduce')"></div>
  40. <div :class="{'arrow-right':direction==='left','arrow-bottom':direction==='top'}"
  41. :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}"
  42. @click.stop="switchDo"></div>
  43. </div>
  44. </div>
  45. </template>
  46. <script type="text/javascript">
  47. export default {
  48. data () {
  49. return {
  50. nowIndex: 0,
  51. noLast: true,
  52. timer: null,
  53. slideChange: '',
  54. arrowWidth: '',
  55. arrowHeight: ''
  56. }
  57. },
  58. computed: {
  59. ulWidth: function () {
  60. return (this.list.length + 2) + "00%";
  61. },
  62. listWidth: function () {
  63. return 100 / (this.list.length + 2)
  64. }
  65. },
  66. mounted(){
  67. if (this.autoplay) {
  68. this.autoSwitch();
  69. }
  70. this.slideChange = this.sildetype || 'ease';
  71. if (this.arrowsize && this.arrowurl) {
  72. this.arrowWidth = this.arrowsize.split(',')[0];
  73. this.arrowHeight = this.arrowsize.split(',')[1];
  74. }
  75. },
  76. props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl', 'arrowsize', 'option', 'direction'],
  77. methods: {
  78. //滑动操作
  79. switchDo(reduce){
  80. clearInterval(this.timer);
  81. //根据reduce判断this.nowIndex的增加或者减少!
  82. if (reduce === 'reduce') {
  83. if (this.nowIndex === 0) {
  84. //如果是滑动切换
  85. this.nowIndex--;
  86. //执行完了这次动画之后,去除过渡效果
  87. setTimeout(() => {
  88. this.nowIndex = this.list.length - 1;
  89. this.noLast = false;
  90. }, 400)
  91. }
  92. else {
  93. this.nowIndex--;
  94. }
  95. }
  96. else {
  97. this.nowIndex++;
  98. }
  99. if (this.nowIndex === this.list.length) {
  100. //执行完了这次动画之后,去除过渡效果
  101. setTimeout(() => {
  102. this.nowIndex = 0;
  103. this.noLast = false;
  104. }, 400)
  105. }
  106. //如果需要自动播放
  107. if (this.autoplay) {
  108. this.autoSwitch();
  109. }
  110. //如果是滑动切换,设置this.noLast,增加过渡效果
  111. this.noLast = true;
  112. },
  113. //自动播放函数
  114. autoSwitch(){
  115. let time = this.time || 4000;
  116. this.timer = setInterval(() => {
  117. this.switchDo();
  118. }, time);
  119. }
  120. }
  121. }
  122. </script>
  123. <style lang="scss">
  124. .ec-slide-img-box {
  125. width: 100%;
  126. height: 100%;
  127. position: relative;
  128. touch-action: none;
  129. }
  130. .ec-slide-img-type {
  131. position: relative;
  132. overflow: hidden;
  133. width: 100%;
  134. height: 100%;
  135. &.ec-slide-img-top {
  136. }
  137. &.ec-slide-img-left {
  138. li {
  139. display: inline-block;
  140. font-size: 0;
  141. }
  142. }
  143. &.ec-slide-img-transparent {
  144. li {
  145. opacity: 0;
  146. transition: opacity 1s;
  147. width: 0;
  148. &.cur {
  149. width: auto;
  150. }
  151. &.show {
  152. opacity: 1;
  153. }
  154. }
  155. }
  156. ul {
  157. font-size: 0;
  158. &.tran {
  159. transition: all .4s;
  160. }
  161. li {
  162. text-align: center;
  163. }
  164. img {
  165. vertical-align: middle;
  166. max-width: 100%;
  167. max-height: 100%;
  168. }
  169. }
  170. }
  171. .ec-slide-arrow {
  172. div {
  173. position: absolute;
  174. z-index: 2;
  175. margin: auto;
  176. top: 0;
  177. bottom: 0;
  178. right: 0;
  179. left: 0;
  180. opacity: .5;
  181. &:hover {
  182. opacity: 1;
  183. }
  184. &.arrow-left {
  185. left: 10px;
  186. right: auto;
  187. }
  188. &.arrow-right {
  189. right: 10px;
  190. left: auto;
  191. transform: rotate(180deg);
  192. }
  193. &.arrow-top {
  194. top: 10px;
  195. bottom: auto;
  196. }
  197. &.arrow-bottom {
  198. bottom: 10px;
  199. top: auto;
  200. transform: rotate(180deg);
  201. }
  202. }
  203. }
  204. .ec-slide-option {
  205. position: absolute;
  206. font-size: 0;
  207. bottom: 10px;
  208. text-align: center;
  209. width: 100%;
  210. z-index: 5;
  211. &.isFirst {
  212. span:first-child {
  213. display: none;
  214. }
  215. }
  216. &.isLast {
  217. span:last-child {
  218. display: none;
  219. }
  220. }
  221. span {
  222. border-radius: 100%;
  223. margin: 0 5px;
  224. background: #fff;
  225. display: inline-block;
  226. width: 10px;
  227. height: 10px;
  228. &.active {
  229. background: #09f;
  230. }
  231. }
  232. &.ec-slide-option-top {
  233. display: table;
  234. width: 10px;
  235. height: 100%;
  236. top: 0;
  237. right: 10px;
  238. margin: auto;
  239. bottom: 0;
  240. span {
  241. margin: 5px 0;
  242. }
  243. div {
  244. display: table-cell;
  245. vertical-align: middle;
  246. }
  247. }
  248. }
  249. </style>

3-6其它切换方式

码农怎么会满足于现状,只有一种切换方式,怎么行,所以我又完善了些:

1.一个透明度的切换方式。

2.当传进的list长度为1的时候只显示图片,不进行任何动画。

3.手机的左右滑动事件的处理(不规范处理)!虽然也是很少功能,但是我在日常开发可以满足!

4.增加上下轮播方式。

完整代码有点多,会导致篇幅过长,在这里不贴了,大家上github看吧!ec-slider

4.小结

好了,今天的开发就到此为止了。起初这个项目我是打算当练手用的,但是后来在项目上使用了,虽然这个写得比较简单,但是效果还不错。现在情况还不是很好,以后有需要也会维护。目前来说,也是建议大家可以玩下这个项目,虽然文章有点长,但是直接看下,边动手写代码,边看文章,会发现。一下子就看完了!这个应该是不错的练手项目,可以熟悉使用vue开发组件!最后,如果大家觉得有哪里写错了,写得不好,欢迎指点!

-------------------------华丽的分割线--------------------
想了解更多,关注关注我的微信公众号:守候书阁

vue组件开发练习--焦点图切换的更多相关文章

  1. 自制jQuery焦点图切换简易插件

    首页经常是需要一个焦点图切换的效果,最近做的项目也正好需要,所以在网上搜索,后面查到了一个半成品的插件,这里我自己修改了一下. js文件夹下面有两个文件夹jquery.jslide.js与jquery ...

  2. vue前端开发那些事——vue组件开发

    vue的学习曲线不是很陡(相比其它框架,如anglarjs),官方文档比较全面,分为基础篇和高级篇.我们刚开始学习的时候,肯定像引用jquery那样,先把vue的js引进来,然后学习基础内容.如果仅仅 ...

  3. 一款jQuery满屏自适应焦点图切换特效

    一款jQuery满屏自适应焦点图切换特效 ,自适应当前浏览器的宽度,可以作为网站整个大背景的却换效果,很不错的一款不jquery特效. 兼容性没的说直接秒杀了IE6.适用浏览器:IE6.IE7.IE8 ...

  4. 基于jQuery打造的选项卡向上弹出jquery焦点图切换特效

    基于jQuery打造的选项卡向上弹出jquery焦点图切换特效 鼠标经过标题栏,会出现层特效向上滑动,并且在同时进行幻灯片切换,效果十分不错. 有兴趣的童鞋可以下载看看,在IE6方面兼容性也不错,只有 ...

  5. 一款jQuery特效编写的大度宽屏焦点图切换特效

    一款jQuery编写的大度宽屏焦点图切换特效 焦点图显示区域有固定的宽度,当前显示宽度之外是一个半透明层显示的其它的焦点图片, 最好的是,此特效兼容IE6以及其它浏览器. 适用浏览器:IE6.IE7. ...

  6. 基于jQuery果冻式按钮焦点图切换代码

    基于jQuery果冻式按钮焦点图切换代码.这是一款基于jQuery+CSS3实现的图片切换代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class=&quo ...

  7. Vue组件开发实例(详细注释)

    Vue组件开发实例: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  8. 简单的Jquery焦点图切换效果

    利用Jquery,优雅的实现焦点图切换 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  9. Vue (三) --- Vue 组件开发

    ------------------------------------------------------------------好心情,会让你峰回路转. 5. 组件化开发 5.1 组件[compo ...

随机推荐

  1. 彻底搞懂 Elasticsearch Java API

    说明 在明确了ES的基本概念和使用方法后,我们来学习如何使用ES的Java API. 本文假设你已经对ES的基本概念已经有了一个比较全面的认识. 客户端 你可以用Java客户端做很多事情: 执行标准的 ...

  2. 数据结构 双向链表 C语言实现

    dlist.h #ifndef __dList_H #define __dlist_H typedef int Item; typedef struct Node *PNode; typedef PN ...

  3. [转帖]字符编码笔记:ASCII,Unicode 和 UTF-8

    字符编码笔记:ASCII,Unicode 和 UTF-8 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 转帖 ...

  4. css动画(transition/transform/animation)

    在开发中,一个好的用户操作界面,总会夹杂着一些动画.css用对少的代码,来给用户最佳的体验感,下面我总结了一些css动画属性的使用方法及用例代码供大家参考,在不对的地方,希望大佬直接拍砖评论. 1 t ...

  5. Spark性能调优:广播大变量broadcast

    Spark性能调优:广播大变量broadcast 原文链接:https://blog.csdn.net/leen0304/article/details/78720838 概要 有时在开发过程中,会遇 ...

  6. 用python实现的21点游戏

    游戏规则 该游戏的规则与实际的玩法应该有点差异,因为我没有去细查21点的确切玩法,只是根据印象中进行了一系列的定义,具体如下: 1.玩家为人类玩家与电脑玩家,共2个玩家.电脑为庄家. 2.先给人类玩家 ...

  7. WAMPSERVER-服务器离线无法切换到在线状态问题的解决

     问题描述:WAMPSERVER-服务器离线“切换到在线状态”则弹出: 解决方案: 本地连接---属性----Internet 协议(TCP/IP)---高级---wins----导入LMHOSTS( ...

  8. 查询SQL Server版本号

    一.查看SQL Server 2005版本号 SELECT @@VERSION 显示以下信息: Microsoft SQL Server 2005 - 9.00.3042.00 (Intel X86) ...

  9. 解决 Ubuntu 19 安装openjdk 8后与openjfx不兼容

    小淘气放假了,孩子在上幼儿园的小朋友,报班也不能太变态嘛, 还是让他自己娱乐的时间多一点,但是现在在家的娱乐就是看电视,听说电视看多了越看越傻,就想方设法的给他找一点娱乐活动,把我闲置的树莓派给他装了 ...

  10. 浅谈RPC框架

    RPC(Remote Promote Call) RPC(Remote Promote Call):一种进程间通信方式.允许像调用本地服务一样调用远程服务. RPC框架的主要目标就是让远程服务调用更简 ...