vue輪播組件實(shí)現(xiàn)$children和$parent 附帶好用的gif錄制工具
1、先提前預(yù)祝大家國(guó)慶節(jié)玩的愉快,我國(guó)慶要見家長(zhǎng)去了(忐忑)
2、忍不住想要為小米正名,雖然我是米粉但是我是理智粉。
24號(hào)不是mix alpha發(fā)布會(huì)啊,看了真滴是驚艷(現(xiàn)場(chǎng)直接有人喊“ 牛逼 ”,看過好多發(fā)布會(huì),就沒有看到這樣直接喊出來“牛逼”的)。不知道大家還記不記得13年那會(huì)吹蘋果的時(shí)候的一塊ppt手機(jī)(其實(shí)是媒體做的圖),但是現(xiàn)在小米做出來了,甚至更好。但是我最近在uc上面那真是到處黑。以前我不相信水軍說法,現(xiàn)在信了。如果關(guān)注小米mix alpha新聞的在uc下面經(jīng)常能看到一個(gè)叫“決勝千里”的人,每次都是千篇一律的復(fù)制黏貼黑。
我想說,沒買過沒資格。就像寫代碼,沒寫過別說懂。寫了你才知道這里面有哪些細(xì)節(jié)和關(guān)鍵因素。
寫這個(gè)組件起因
記得就這兩天有掘友發(fā)一個(gè)沸點(diǎn)說找女票千萬別找同行,好了,曾經(jīng)我是erp軟件實(shí)施,現(xiàn)在轉(zhuǎn)前端。女票也是前端。然后她發(fā)我一個(gè)鏈接(打不開看gif圖):http://ipark.jsboon.com/static/dashboard/yjw/yjw.html
這個(gè)鏈接的最右側(cè)有一個(gè)輪播的效果。說起來這整個(gè)頁(yè)面是不咋的,不過里面涉及的東西都比較復(fù)雜。 附帶gif錄制工具:http://www.zdfans.com/html/1754.html
回到剛才說的,女票,對(duì)女票。不懂問我,就像之前評(píng)論的,干脆讓我寫得了。這下好了報(bào)應(yīng)來了。(說起來真是無語,她比我早干一年,結(jié)果還不如我寫了1年前端)
說起來我還沒寫過這種輪播組件,但是之前去看過源碼,并且了解過。如果是寫死的那種確實(shí)比較簡(jiǎn)單。但是我們今天用vue封裝一個(gè)組件。
一、知識(shí)點(diǎn)涉及
1、vue組件化開發(fā)
2、vue組件嵌套組,就是兩個(gè)組件相互耦合,然后必須配合使用的那種。參考elementUI里面的表單組件(分為from組件,item組件)或者輪播組件。
vue的 $children和 $parent
3、css動(dòng)畫和形變
二、開始寫組件
1、先寫你的框,主組件
這個(gè)是容器,負(fù)責(zé)組件定位和組件的整體運(yùn)作的
html部分
<div
@mouseenter.stop="handleMouseEnter"
@mouseleave.stop="handleMouseLeave"
class="dht-swiper-side"
:style="{ zIndex: zIndex }"
>
<slot></slot>
</div>
主要兩個(gè)鼠標(biāo)事件: mouseenter和 mouseleave
第一個(gè)就是鼠標(biāo)在元素上負(fù)責(zé)停止定時(shí)器,第二個(gè)就是鼠標(biāo)離開重啟定時(shí)器
對(duì)應(yīng)的props和監(jiān)聽
props: {
// 時(shí)間間隔
interval: {
type: Number,
default: 8000
},
//是否自動(dòng)播放
autoplay: {
type: Boolean,
default: true
},
zIndex: {
type: Number,
default: 2000
},
// x軸變化
axisx: {
type: Number,
default: 1000
}
},
watch: {
autoplay(val) {
val ? this.startTimer() : this.stopTimer();
}
},
data() {
return {
// 計(jì)時(shí)器
timer: "",
//子元素
items: [],
// 當(dāng)前顯示的元素
active: 0
};
},
看看就好,沒啥多說的,我感覺挺清晰的
2、寫你的子組件
這里必須跳躍一下,為什么呢?
因?yàn)椋褐鹘M件主要負(fù)責(zé)動(dòng)畫運(yùn)作和容器的作用。定義好你要的參數(shù)之后,其實(shí)主組件你直接看代碼是不不符合編寫邏輯的
有了主組件之后,我需要有子元素才能動(dòng)起來,所以先把子元素加載進(jìn)來
html部分
<div class="dht-swiper-side-item" :style="itemStyle"> <slot></slot> </div>
js核心部分
created() {
//元素創(chuàng)建和需要更新父元素屬性
this.$parent && this.$parent.updateItems();
},
beforeMount() {},
mounted() {},
destroyed() {
//元素銷毀和需要更新父元素屬性
this.$parent && this.$parent.updateItems();
},
這里主要是創(chuàng)建元素的時(shí)候需要把元素加入主組件的items中,銷毀的時(shí)候同樣進(jìn)行更新
主組件的更新代碼
// 更新元素
updateItems() {
this.items = this.$children.filter(
// 更新元素需要確認(rèn)為指定的子元素
child => child.$options.name === "dhtSwiperSideItem"
);
},
css核心部分
css部分主要是定義動(dòng)畫效果,和基礎(chǔ)css,主要是看動(dòng)畫部分
.dht-swiper-side-item {
position: absolute;
transition: all 1s ease;
transform: translateX(1000px);
// 抖動(dòng)動(dòng)畫
@keyframes mymove {
0% {
left: 0;
}
50% {
left: 15px;
}
100% {
left: 0;
}
}
}
3、一般彈窗動(dòng)畫之類的編寫原理講解
1、不能用display:none,因?yàn)槟菢釉厥侵苯语@示出來的,動(dòng)畫是無法有的。
2、舉例:下方彈窗劃出
其實(shí)在寫這些彈窗的時(shí)候元素已經(jīng)在頁(yè)面上面加載好了,只是被我們隱藏到顯示器之外了。
所以我們要做的是在點(diǎn)擊顯示的時(shí)候把元素位移回來
3、所以其實(shí)頁(yè)面上基本的動(dòng)畫都是先放在你看不到的地方,然后再通過 transform
形變css給移動(dòng)回來的。我這次的組件也是一樣的。
4、主組件操作
1、回顧一下,剛才我們先寫了主組件,主組件加載子組件,子組件會(huì)調(diào)用主組件函數(shù),讓主組件去更新自己的items,提前存好。方便使用
2、既然我們主組件拿到了子組件了,那么就可以直接操作子組件進(jìn)行操作,其實(shí)核心原理在于主組件之間操作子組件。(我看了elementUI源碼的走馬燈部分,寫的比我復(fù)雜。)
3、定時(shí)器部分
//開始計(jì)時(shí)器
startTimer() {
//預(yù)先執(zhí)行一次,保證不會(huì)出現(xiàn)第一次運(yùn)行延遲雙倍實(shí)際
this.play();
// 攔截處理
if (this.interval <= 0 || !this.autoplay || this.timer) return;
this.timer = setInterval(() => {
this.play();
}, this.interval);
},
這塊其實(shí)沒啥,除了預(yù)先的攔截剩下的就是啟動(dòng)定時(shí)器,然后運(yùn)行動(dòng)畫播放函數(shù)
4、核心播放函數(shù)部分
//播放實(shí)際運(yùn)行函數(shù)
play() {
let len = this.items.length - 1;
let now = this.active > len ? 0 : this.active;
let old = this.active - 1 < 0 ? 0 : this.active - 1;
//console.log("當(dāng)前", now, "老的", old);
//關(guān)閉老元素
this.items[old].show = false;
this.items[old].itemStyle = {
transition: "all 1.5s ease",
transform: `translateX(${this.axisx}px)`
};
//顯示新元素
this.items[now].show = true;
this.items[now].itemStyle = {
transition: "all 1.5s ease",
transform: "translateX(0)",
animation: "mymove 1.5s 2"
};
//記錄數(shù)據(jù)
this.active = now + 1;
}
這個(gè)其實(shí)很簡(jiǎn)單,每次運(yùn)行的時(shí)候處理一下數(shù)據(jù),拿到當(dāng)前要運(yùn)行的子元素id和老的元素,當(dāng)前的展示,老的移動(dòng)回去。最后記錄一下新的id
這里有一個(gè)坑點(diǎn):就是animation部分,記得運(yùn)行2次,不然只是一次會(huì)導(dǎo)致下面的元素看不到抖動(dòng)效果。原因是在移動(dòng)的時(shí)候就抖動(dòng)完畢了。
5、主組件css部分
.dht-swiper-side {
position: absolute;
z-index: 2000;
right: 0;
display: flex;
flex-flow: row;
width: 100%;
}
三、組件文檔
| dht-swiper-side | 側(cè)邊輪播組件 | interval | Number | 5000 | 時(shí)間間隔,默認(rèn)5秒轉(zhuǎn)換一次 | 必須給該組件指定寬度,否則無法正常顯示。 | 內(nèi)部子元素展示做最側(cè)位置主要由該組件的寬度定義 |
| autoplay | Boolean | TRUE | 是否自動(dòng)播放,咱不支持false | ||||
| zIndex | Number | 2000 | 組件層級(jí) | ||||
| axisx | Number | 1000 | 隱藏的子元素位置,px單位,默認(rèn)1000。當(dāng)內(nèi)部元素寬度過大時(shí)可以調(diào)節(jié)該參數(shù) | ||||
| dht-swiper-side-item | dht-swiper-side | dht-swiper-side的子組件,用于存放內(nèi)容 |
四、個(gè)人組件效果展示
<dht-swiper-side class="main">
<dht-swiper-side-item>
<div class="item">我是組件1</div>
</dht-swiper-side-item>
<dht-swiper-side-item>
<div class="item">我是組件2</div>
</dht-swiper-side-item>
<dht-swiper-side-item>
<div class="item">我是組件3</div>
</dht-swiper-side-item>
<dht-swiper-side-item>
<div class="item">我是組件4</div>
</dht-swiper-side-item>
</dht-swiper-side>
.main {
width: 500px;
.item {
width: 100px;
height: 100px;
background: #009966;
border: #409eff 1px solid;
text-align: center;
line-height: 100px;
}
}
主組件全部代碼
<template>
<div
@mouseenter.stop="handleMouseEnter"
@mouseleave.stop="handleMouseLeave"
class="dht-swiper-side"
:style="{ zIndex: zIndex }"
>
<slot></slot>
</div>
</template>
<script>
export default {
name: "dhtSwiperSide",
props: {
// 時(shí)間間隔
interval: {
type: Number,
default: 8000
},
//是否自動(dòng)播放
autoplay: {
type: Boolean,
default: true
},
zIndex: {
type: Number,
default: 2000
},
// x軸變化
axisx: {
type: Number,
default: 1000
}
},
watch: {
autoplay(val) {
val ? this.startTimer() : this.stopTimer();
}
},
data() {
return {
// 計(jì)時(shí)器
timer: "",
//子元素
items: [],
// 當(dāng)前顯示的元素
active: 0
};
},
beforeCreate() {},
created() {
this.$nextTick(() => {
this.updateItems();
this.startTimer();
this.$children[0].show = true;
});
},
beforeMount() {},
mounted() {},
destroyed() {
clearInterval(this.timer);
},
methods: {
handleMouseEnter() {
this.stopTimer();
},
handleMouseLeave() {
this.startTimer();
},
//開始計(jì)時(shí)器
startTimer() {
//預(yù)先執(zhí)行一次,保證不會(huì)出現(xiàn)第一次運(yùn)行延遲雙倍實(shí)際
this.play();
// 攔截處理
if (this.interval <= 0 || !this.autoplay || this.timer) return;
this.timer = setInterval(() => {
this.play();
}, this.interval);
},
// 停止計(jì)時(shí)器
stopTimer() {
clearInterval(this.timer);
},
// 更新元素
updateItems() {
this.items = this.$children.filter(
// 更新元素需要確認(rèn)為指定的子元素
child => child.$options.name === "dhtSwiperSideItem"
);
},
//播放實(shí)際運(yùn)行函數(shù)
play() {
let len = this.items.length - 1;
let now = this.active > len ? 0 : this.active;
let old = this.active - 1 < 0 ? 0 : this.active - 1;
//console.log("當(dāng)前", now, "老的", old);
//關(guān)閉老元素
this.items[old].show = false;
this.items[old].itemStyle = {
transition: "all 1.5s ease",
transform: `translateX(${this.axisx}px)`
};
//顯示新元素
this.items[now].show = true;
this.items[now].itemStyle = {
transition: "all 1.5s ease",
transform: "translateX(0)",
animation: "mymove 1.5s 2"
};
//記錄數(shù)據(jù)
this.active = now + 1;
}
}
};
</script>
<style lang="scss">
.dht-swiper-side {
position: absolute;
z-index: 2000;
right: 0;
display: flex;
flex-flow: row;
width: 100%;
}
</style>
子組件全部代碼
<template>
<div class="dht-swiper-side-item" :style="itemStyle">
<slot></slot>
</div>
</template>
<script>
export default {
name: "dhtSwiperSideItem",
data() {
return {
show: false,
defaultStyle: {},
itemStyle: {}
};
},
watch: {},
beforeCreate() {},
created() {
//元素創(chuàng)建和需要更新父元素屬性
this.$parent && this.$parent.updateItems();
},
beforeMount() {},
mounted() {},
destroyed() {
//元素銷毀和需要更新父元素屬性
this.$parent && this.$parent.updateItems();
},
methods: {}
};
</script>
<style lang="scss">
.dht-swiper-side-item {
position: absolute;
transition: all 1s ease;
transform: translateX(1000px);
// 抖動(dòng)動(dòng)畫
@keyframes mymove {
0% {
left: 0;
}
50% {
left: 15px;
}
100% {
left: 0;
}
}
}
</style>
致謝
感謝elementUI開源代碼,本組件有部分是直接拷貝的elementUI的Carousel的代碼。
總結(jié)
以上所述是小編給大家介紹的vue輪播組件實(shí)現(xiàn)$children和$parent 附帶好用的gif錄制工具,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
在Vue中如何實(shí)現(xiàn)打字機(jī)的效果
這篇文章主要介紹了在Vue中如何實(shí)現(xiàn)打字機(jī)的效果,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
vue項(xiàng)目實(shí)現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了vue項(xiàng)目實(shí)現(xiàn)圖片上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
vue使用計(jì)算屬性完成動(dòng)態(tài)滑竿條制作
這篇文章主要介紹了vue使用計(jì)算屬性完成動(dòng)態(tài)滑竿條制作,文章圍繞計(jì)vue算屬制作動(dòng)態(tài)滑竿條的相關(guān)代碼完成內(nèi)容,需要的朋友可以參考一下2021-12-12
解決Vue 通過下表修改數(shù)組,頁(yè)面不渲染的問題
下面小編就為大家分享一篇解決Vue 通過下表修改數(shù)組,頁(yè)面不渲染的問題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-03-03
快速修改antd?vue單個(gè)組件的默認(rèn)樣式
這篇文章主要介紹了快速修改antd?vue單個(gè)組件的默認(rèn)樣式方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2022-08-08
vue-cli項(xiàng)目代理proxyTable配置exclude的方法
今天小編就為大家分享一篇vue-cli項(xiàng)目代理proxyTable配置exclude的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09
Vue實(shí)現(xiàn)回到頂部和底部動(dòng)畫效果
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)回到頂部和底部動(dòng)畫效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07

