今天來做個幻燈組件的筆記,這里只記錄實現邏輯,不對樣式代碼做展示。
一個幻燈片組件需要實現的功能如下:
1、幻燈片的循環播放;
2、幻燈片分頁;
3、幻燈片標題的顯示;
4、鼠標進入,停止幻燈切換;
5、鼠標離開,繼續幻燈切換;
6、點擊相應幻燈,或幻燈標題,觸發不同事件(根據實際需求做處理);
7、點擊頁碼,實現幻燈切換及循環播放。
效果如下:
具體步驟
第一步:新建slideShow.vue組件;
<template>
<div>hello world {{ x }}</div>
</template>
<script>
export default {
name: "slideShow",
data() {
return {
x : '我是slideShow'
}
}
}
</script>
第二步:在父組件中引入
// template
<div class="index-right">
<slide-show></slide-show>
</div>
// script
import slideShow from '../components/slideShow'
export default {
components: {
slideShow
},
data() {
return {
}
}
}
這時候可以看到效果:slideShow組件的內容已被渲染到父組件
第三步:在父組件為幻燈片動態綁定要顯示的內容,并在子組件接收。
知識點:父、子組件通信。
父組件 :template
<slide-show :slides="slides"></slide-show>
script :data
slides: [
{
src: require('../assets/slideShow/pic1.jpg'),
title: 'xxx1',
href: 'detail/analysis'
},
{
src: require('../assets/slideShow/pic2.jpg'),
title: 'xxx2',
href: 'detail/count'
},
{
src: require('../assets/slideShow/pic3.jpg'),
title: 'xxx3',
href: 'http://xxx.xxx.com'
},
{
src: require('../assets/slideShow/pic4.jpg'),
title: 'xxx4',
href: 'detail/forecast'
}
]
子組件,這里限制了父組件傳參的類型
props: {
slides: {
type: Array,
default: []
}
},
mounted () {
console.log(this.slides)
}
這里可以看到,子組件接收到了父組件傳過來的參數
第四步:把父組件傳來的參數展示在模板;
<template>
<div class="slide-show">
<div class="slide-img">
<a href="xxx">
<img :src="slides[0].src">
</a>
</div>
<h2>{{ slides[0].title }}</h2>
<ul class="slide-pages">
<li><</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>></li>
</ul>
</div>
</template>
效果如下
第五步:分頁,讓幻燈片切換
<template>
<div class="slide-show">
<div class="slide-img">
<a :href="slides[nowIndex].href">
<img :src="slides[nowIndex].src">
</a>
</div>
<h2>{{ slides[nowIndex].title }}</h2>
<ul class="slide-pages">
<li><</li>
<li v-for="(item, index) in slides" @click="goto(index)">
<a>{{ index + 1 }}</a>
</li>
<li>></li>
</ul>
</div>
</template>
methods: {
goto(index) {
this.nowIndex = index
}
},
實現頁碼上一頁、下一頁功能;使用計算屬性,通過一個方法實現;
知識點:計算屬性。
<li @click="goto(prevIndex)"><</li>
<li v-for="(item, index) in slides" @click="goto(index)">
<a :class="{on: index === nowIndex}">{{ index + 1 }}</a>
</li>
<li @click="goto(nextIndex)">></li>
computed: {
prevIndex () {
if (this.nowIndex === 0) {
return this.slides.length - 1
}
else {
return this.nowIndex - 1
}
},
nextIndex () {
if (this.nowIndex === this.slides.length - 1) {
return 0
}
else {
return this.nowIndex + 1
}
}
},
第六步:讓幻燈片自動切換
父組件動態傳參:幻燈片自動切換時間間隔
<slide-show :slides="slides" :inv="invTime"></slide-show>
// 在data中注冊
invTime: 2000,
子組件
// props 注冊組件的動態屬性
inv: {
type: Number,
default: 1000
}
// 添加 methods實現幻燈片切換
runInv () {
this.invId = setInterval(() => {
this.goto(this.nextIndex)
}, this.inv)
},
// 在mounted中調用方法
mounted () {
this.runInv();
}
第七步:鼠標事件
// 在methods注冊一個清除切換的方法
clearInv () {
clearInterval(this.invId)
}
// 在根節點添加鼠標時間
<template>
<div class="slide-show" @mouseover="clearInv" @mouseout="runInv">
...
第八步:高級功能:圖片的動畫效果
知識點:樣式標簽transition的使用;
難點:這里的兩個nowIndex一個是新值一個是舊值,在goto函數中改變。
// 幻燈片切換添加transition
<a :href="slides[nowIndex].href">
<transition name="slide-trans">
<img v-if="isShow" :src="slides[nowIndex].src">
</transition>
<transition name="slide-trans-old">
<img v-if="!isShow" :src="slides[nowIndex].src">
</transition>
</a>
// 為變量注冊初始值
isShow:true
// 修改goto函數
goto(index) {
this.isShow = false
setTimeout(() => {
this.isShow = true
this.nowIndex = index
}, 10)
},
// 添加樣式
.slide-trans-enter-active {
transition: all .5s;
}
.slide-trans-enter {
transform: translateX(900px);
}
.slide-trans-old-leave-active {
transition: all .5s;
transform: translateX(-900px);
}
第九步:子組件切換:觸發父組件的事件
知識點:子組件向父組件通信
// 所有的切換都是在goto函數中,所以在goto函數調用事件$emit
goto(index) {
this.isShow = false
setTimeout(() => {
this.isShow = true
this.nowIndex = index
this.$emit('onChange',index)
}, 10)
},
// 在父組件的子組件標簽中綁定事件
<slide-show :slides="slides" :inv="invTime" @onChange="doSomethingOnSlideChange"></slide-show>
// 在methods中實現綁定的事件
methods: {
doSomethingOnSlideChange() {
console.log('幻燈片切換了,父組件要做點什么')
}
},