根据huangyi老师的慕课网vue项目跟着做的,下面大概记录了下思路

1.轮播图的图

先不做轮播图逻辑部分,先把数据导进来,看看什么效果。在recommend组件新建一个recommends的数组,用这个数组来接受数据的录播图部分。然后再轮播图的插槽部分添加图片,代码如下

<slider>
<div v-for="(item,index) in recommends" :key="index">
<a :href="item.linkUrl">
<img :src="item.picUrl">
</a>
</div>
</slider>
// recommends.vue
<script>
data() {
return {
recommends: []
}
},
methods: {
_getRecommend() {
getRecommend().then(res => {
if (res.code === ERR_OK) {
this.recommends = res.data.slider
console.log(this.recommends)
}
)
}
},
</script>

但是现在轮播图是糊的,所以就要按着需求来自己做slider组件。

首先,我们给轮播图sliderGroup,设置一个总的宽度。

<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot></slot>
</div>
<div class="dots"></div>
</div>

要设置sliderGroup的宽度的话,我们要在渲染好dom元素的时候再设置宽度,所以我们要在mouted这个钩子函数里执行设置宽度,_setSliderWidth()和 _initSlider()分别是设置宽度和加入滚动效果。这里是为了分离,不让mounted这个钩子函数里有太多东西,然后不好改逻辑。

mounted() {
setTimeout(() => {
this._setSliderWidth()
this._initSlider()
}, 20)
},

下面就是设置SliderGroup的宽度,其实中我们设置的主要方法,就是把slider的宽度给sliderGroupd的每个children,其中的slider-item属性是让他们左浮动的。然后让他们超出来的都隐藏掉。然后最后因为loop是循环轮播,要给slider前后各加一个宽度,这个是基础了,不懂得百度轮播图原理。然后最后让sliderGroup的宽度变成通过slot传进来的图片加2的宽度。

methods: {
_setSliderWidth() {
this.children = this.$refs.sliderGroup.children let width = 0
let sliderWidth = this.$refs.slider.clientWidth
for (let i = 0; i < this.children.length; i++) {
let child = this.children[i]
addClass(child, 'slider-item') child.style.width = sliderWidth + 'px'
width += sliderWidth
}
if (this.loop) {
width += 2 * sliderWidth
}
this.$refs.sliderGroup.style.width = width + 'px'
}
}

addClass方法不是系统自带的,是自己定义的,放在项目的src/common/js/dom/js里

export function addClass(el, className) {
if (hasClass(el, className)) {
return
} let newClass = el.className.split(' ')
newClass.push(className)
el.className = newClass.join(' ')
} export function hasClass(el, className) {
let reg = new RegExp('(^|\\s)' + className + '(\\s|$)')
return reg.test(el.className)
}

在设置完宽度以后,需要在recommend.vue设置一下加入addClass的时间,因为getRecommend这个方法是异步的,所以如果在dom渲染完后的时候在执行addclass方法,此时还没有获得到数据,所以也就没有slot里面的数据,所以要在slder组件外侧的div中设置一个v-if

<div v-if="recommends.length" class="slider-wrapper">
<slider>
<div v-for="(item,index) in recommends" :key="index">
<a :href="item.linkUrl">
<img :src="item.picUrl">
</a>
</div>
</slider>
</div>

当轮播图可以正确显示的时候,我们需要给轮播图添加滑动。我们用better-scroll,直接在npm上安装,然后在script标签里引入BScroll, 然后传入合适的参数,就可以了。

 _initSlider() {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false,
snap: true,
snapLoop: this.loop,
snapThreshold: 0.3,
snapSpeed: 400,
click: true
})
}

2.轮播图的dots

首先,我们要通过children.length来新建dots,在哪里新建呢?在mounted里

mounted() {
setTimeout(() => {
this._setSliderWidth()
this._initDots()
this._initSlider()
}, 20)
}

然后顺应着新建一个_initDots方法,这样可以有效的分离,业务逻辑比较清晰。

_initDots() {
this.dots = new Array(this.children.length)
},

现在的程度是仅仅有dots的静态了(css做出样式),然后我们需要根据页面来设置active-dots。所以我们需要在_initSlider()方法中监听scrollEnd事件,这个时间是better-scroll的,如果没导入就没有。

this.slider.on('scrollEnd', () => {
let pageIndex = this.slider.getCurrentPage().pageX
// 这个pageIndex -1是因为前面有一张为了无缝连接轮播图的。需要把他弄掉
if (this.loop) {
pageIndex -= 1
}
this.currentPageIndex = pageIndex
})

然后配合js,我们在html绑定相应的class就行了。

 <div class="dots">
<span
class="dot"
v-for="(item,index) in dots"
:key="index"
:class="{active:currentPageIndex === index}"
></span>
</div>

这样就就可以实现轮播带着dots一起动的效果了,接下来做自动播放功能

3. 轮播图自动播放

自动播放的时机,就是在新建轮播图完成的时候,也就是在mounted钩子里,定义一个_play方法

 mounted() {
setTimeout(() => {
this._setSliderWidth()
this._initDots()
this._initSlider()
if (this.autoPlay) {
this._play()
}
}, 20)
}

然后我们顺着去找methods里定义_play()这个方法。

_play() {
let pageIndex = this.currentPageIndex + 1
if (this.loop) {
pageIndex += 1
}
this.timer = setTimeout(() => {
// 0 代表y方向,400表示间隔
this.slider.goToPage(pageIndex, 0, 400)
}, this.interval)
}

但是这个在mounted钩子里,我们只调用了依次goToPage方法。这很不爽。所以需要我们在想办法,让每次换页的时候都去调用一下,拿着还不好说嘛,用上次的scrollEnd事件,所以只需要在上次那个地方添加一些方法就OK了

this.slider.on('scrollEnd', () => {
let pageIndex = this.slider.getCurrentPage().pageX
if (this.loop) {
pageIndex -= 1
}
this.currentPageIndex = pageIndex if (this.autoPlay) {
clearTimeout(this.timer)
this._play()
}
})

OK,现在轮播图的dots,滑动,自动播放功能就完成了。下面是组件完整的代码

<template>
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot></slot>
</div>
<div class="dots">
<span
class="dot"
v-for="(item,index) in dots"
:key="index"
:class="{active:currentPageIndex === index}"
></span>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import BScroll from 'better-scroll'
import { addClass } from 'common/js/dom'
export default {
data() {
return {
dots: [],
currentPageIndex: 0
}
},
props: {
// 是否可以循环轮播
loop: {
type: Boolean,
default: true
},
// 是否可以自动轮播
autoPlay: {
type: Boolean,
default: true
},
// 自动轮播时间间隔
interval: {
type: Number,
default: 4000
}
},
mounted() {
setTimeout(() => {
this._setSliderWidth()
this._initDots()
this._initSlider()
if (this.autoPlay) {
this._play()
}
}, 20)
window.addEventListener('resize', () => {
if (!this.silder) {
return
}
this._setSliderWidth(true)
this.slider.refresh()
})
},
methods: {
_setSliderWidth(isResize) {
this.children = this.$refs.sliderGroup.children let width = 0
let sliderWidth = this.$refs.slider.clientWidth
for (let i = 0; i < this.children.length; i++) {
let child = this.children[i]
addClass(child, 'slider-item') child.style.width = sliderWidth + 'px'
width += sliderWidth
}
if (this.loop && !isResize) {
width += 2 * sliderWidth
}
this.$refs.sliderGroup.style.width = width + 'px'
},
_initSlider() {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false,
snap: true,
snapLoop: this.loop,
snapThreshold: 0.3,
snapSpeed: 400,
click: true
})
this.slider.on('scrollEnd', () => {
let pageIndex = this.slider.getCurrentPage().pageX
if (this.loop) {
pageIndex -= 1
}
this.currentPageIndex = pageIndex if (this.autoPlay) {
clearTimeout(this.timer)
this._play()
}
})
},
_initDots() {
this.dots = new Array(this.children.length)
},
_play() {
let pageIndex = this.currentPageIndex + 1
if (this.loop) {
pageIndex += 1
}
this.timer = setTimeout(() => {
// 0 代表y方向,400表示间隔
this.slider.goToPage(pageIndex, 0, 400)
}, this.interval)
}
}
}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">
@import '~common/stylus/variable'
.slider
min-height: 1px
.slider-group
position: relative
overflow: hidden
white-space: nowrap
.slider-item
float: left
box-sizing: border-box
overflow: hidden
text-align: center
a
display: block
width: 100%
overflow: hidden
text-decoration: none
img
display: block
width: 100%
.dots
position: absolute
right: 0
left: 0
bottom: 12px
text-align: center
font-size: 0
.dot
display: inline-block
margin: 0 4px
width: 8px
height: 8px
border-radius: 50%
background: $color-text-l
&.active
width: 20px
border-radius: 5px
background: $color-text-ll
</style>

做一个vue轮播图组件的更多相关文章

  1. Vue2 轮播图组件 slide组件

    Vue2原生始轮播图组件,支持宽度自适应.高度设置.轮播时间设置.左右箭头按钮控制,圆点按钮切换,以及箭头.圆点按钮是否显示. <v-carousel :slideData="slid ...

  2. vue自定义轮播图组件 swiper

    1.banner 组件 components/Banner.vue <!-- 轮播图 组件 --> <template> <div class="swiper- ...

  3. Vue实现音乐播放器(七):轮播图组件(二)

    轮播图组件 <template> <div class="slider" ref="slider"> <div class=&qu ...

  4. vue移动音乐app开发学习(三):轮播图组件的开发

    本系列文章是为了记录学习中的知识点,便于后期自己观看.如果有需要的同学请登录慕课网,找到Vue 2.0 高级实战-开发移动端音乐WebApp进行观看,传送门. 完成后的页面状态以及项目结构如下: 一: ...

  5. iOS回顾笔记(05) -- 手把手教你封装一个广告轮播图框架

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  6. 使用原生js将轮播图组件化

    代码地址如下:http://www.demodashi.com/demo/11316.html   这是一个轮播图组件,这里是代码地址,需要传入容器的id和图片地址,支持Internet Explor ...

  7. 原生JS面向对象思想封装轮播图组件

    原生JS面向对象思想封装轮播图组件 在前端页面开发过程中,页面中的轮播图特效很常见,因此我就想封装一个自己的原生JS的轮播图组件.有了这个需求就开始着手准备了,代码当然是以简洁为目标,轮播图的各个功能 ...

  8. 03 uni-app框架学习:轮播图组件的使用

    1.轮播图组件的使用 参照官方文档 2.在页面上加入这个组件 3.在页面中引去css样式 并编写样式 ps:upx单位是什么 简单来说 就相当于小程序中的rpx 是一个自适应的单位 会根据屏幕宽度自动 ...

  9. bootstrap轮播图组件

    一.轮播图组件模板(官方文档) <div id="carousel-example-generic" class="carousel slide" dat ...

随机推荐

  1. 最小割最大流定理&残量网络的性质

    最小割最大流定理的内容: 对于一个网络流图 $G=(V,E)$,其中有源点和汇点,那么下面三个条件是等价的: 流$f$是图$G$的最大流 残量网络$G_f$不存在增广路 对于$G$的某一个割$(S,T ...

  2. 松软科技web课堂:SQLServer之MID() 函数

    MID() 函数 MID 函数用于从文本字段中提取字符. SQL MID() 语法 SELECT MID(column_name,start[,length]) FROM table_name 参数 ...

  3. [browser srceen]、很多未知望大神告知、简单写了个拖拽

    未知作用的有.如果也有像我1样好奇的小伙伴了解了麻烦告知 // console.log(window.screen.availWidth);//未知效果 // console.log(window.s ...

  4. ios中友盟集成好使用总结

    参考链接:https://www.jianshu.com/p/a8ff46a7c966

  5. iOS----------iPhone导出手机所有短信

    第一步:手机连接到itunes  选择本电脑备份   备份的时候不要加密  然后立即备份 第二步:前往文件夹,找到itunes的备份路径~/Library/Application Support/Mo ...

  6. Google Chome浏览器下如何开发UHF读写器

    google Chrome浏览器不支持ocx,也就不能通过ocx来连接UHF读写器,只能使用RFID读写器云服务插件,通过javascript语言来连接和操控UHF读写器YW-602H.RFID读写器 ...

  7. 【课件】git零基础快速入门实战--重点讲解,在实际生产中整合idea对版本、分支的管理等

    1.git简单描述 git是重要的版本管理工具,几乎每个码农都有自己的git账号管理自己的代码,同时很多公司也是用git管理公司的代码, 因此掌握git在实际生产中的常规使用非常重要. 2.git学习 ...

  8. 读书笔记_python网络编程3(5)

    5. 网络数据与网络错误 应该如何准备需要传输的数据? 应该如何对数据进行编码与格式化? Py程序需要提供哪些类型的错误? 5.1. 字节与字符串 PC与网卡都支持将字节作为通用传输单元.字节将8比特 ...

  9. June 30th, 2019. Week 26th, Sunday

    It's so easy to be careless, it takes courage and courage to care. 不在乎很容易,但在乎却需要很多勇气. Sometimes it w ...

  10. JAVA中int转String类型有三种方法

    String.valueOf(i) Integer.toString(i) i+"" i+""也就是一个int型的常量.+上个空的字符串,这里牵涉到了strin ...