作者 : 混元霹靂手-ziksang
我這裡就不帖圖了,marquee就是輪播廣告或公告。。。。。
給vux打打廣告吧,我感覺功能最強大的還是vux ui庫,我帶大家看看這玩意如何實現的,你別看學別人寫元件,還能學到一些你平常用不到的弱知識點,雙擊,666666,沒毛病。
在這裡打個廣告,如果有誰私底下有興趣的,想和我一起打造一套基礎vue的ui元件庫的話,請聯絡我!!!!!!
接下來還是按著我們約定的來
2.程式碼執行vue-cli 2.1版本
3.元件程式碼都在components資料夾裡
4.主程式碼邏輯都在 App.vue資料夾裡
我什麼都不要我只要
贊
在vux中marquee裡分成了兩元件,分別進行slot
1.第一個元件中slot是用來放入每個marquee節點
2.第二個元件中solt是在每個節點放入文案
這有什麼好處呢?
1.第一可以讓程式碼更清楚,在第一個組進行邏輯層編寫和初始化配置
2.第二個元件進行邏輯啟動
這裡的無逢滾動又是如何做到的呢?
1.這裡進行了上滾動和下滾動,分別進行了不同的初始化配置
2.通過cloneChild(true)進行深複製分別辨別direction的位置進行配置
在compoents>marquee>marquee.vue
我們先看看template部分
<template>
<div class="vux-marquee" :style="{height: height + 'px'}">
<ul class="vux-marquee-box" ref="box" :style="{transform: `translate3d(0,${currenTranslateY}px,0)`, transition: `transform ${noAnimate ? 0 : duration}ms`}">
<slot></slot>
</ul>
</div>
</template>複製程式碼
解析:
1.首先在class='vux-marquee'dom節點中, 對height進行了樣式配置,這裡的hight起什麼作用,之所以要配置,肯定是要有作用才配置,就是對第一條marquee公告的高度進行復制放入,來進行每條的顯示
2.{transform:
translate3d(0,${currenTranslateY}px,0)對每條顯示的位置進行改動
3.
transform ${noAnimate ? 0 : duration}ms}
對初化第一條和無逢滾動接入的一個時間點我們對動畫時間進行0s設定
再看看script中prop部分
props: {
interval: {
type: Number,
default: 2000
},
duration: {
type: Number,
default: 300
},
direction: {
type: String,
default: 'up'
}
},複製程式碼
對外暴露的三個屬性
1.interval:每個marquee條目間格多少換一次
2.duration:對動畫時長多少設定
3.direction:對上或下marquee的配置
再看看script中data資料的
data () {
return {
currenTranslateY: 0,
height: '',
length: 0,
currentIndex: 0,
noAnimate: false
}
},複製程式碼
1.currenTranslateY :改變的y軸解度存放
2.height:高度存放的值存放
3.length:marquee條目的總長度存放
4.當前每個條目的index下標值存放
5.是否是進行動化的配置值存放
再看看script中methods中三大方法
init () {
this.destroy()
if (this.cloneNode) {
this.$refs.box.removeChild(this.cloneNode)
}
this.cloneNode = null
let firstItem = this.$refs.box.firstElementChild //獲取box節點下的第一個元素
if (!firstItem) {
return false
} //如果沒有li元素則退出
this.length = this.$refs.box.children.length //獲得ul下li節點的長度
this.height = firstItem.offsetHeight
if (this.direction === 'up') {
this.cloneNode = firstItem.cloneNode(true)
this.$refs.box.appendChild(this.cloneNode)
} else {
this.cloneNode = this.$refs.box.lastElementChild.cloneNode(true)
this.$refs.box.insertBefore(this.cloneNode, firstItem)
}
},複製程式碼
這裡是初始化配置方法,我們就挑重要的說
1.this.cloneNode=null
進行存放,以但於從新渲染時可以刪除標記
2.firstItem
這個變數是拿全marquee盒子中第一個條目dom節點
3.this.length
是所有條目的總數
4.this.height
是第一個條目的高度,然後滾動檢視就基於第一個條目的高度進行配置
5.在最後的一個this.direction === 'up'
這個判斷語句中,可以看出對屬性dircetion來進行初始化配置,這裡同時也是對無逢滾動的操作進行配置,如果是向上滾動,就深度複製第一條目進行最後節點插入,如果是down
,就對最後一個條目深度複製插入到第一個條目前
go (toFirst) {
this.noAnimate = true
if (toFirst) {
this.currentIndex = 0
this.currenTranslateY = 0
} else {
this.currentIndex = this.length - 1 //當我們向下marquee的時候,此時最後一個下標為總長度-1
this.currenTranslateY = -(this.currentIndex + 1) * this.height
//因為如果向下的話,我們在li的最項部插入了最後一dom此時我們要+1
}
}複製程式碼
這個go方法就是中間轉換層
1.在無逢滾動時候對動畫時間設為false則為0,
2.如果tofirst引數為ture時則是向上滾動配置
3.如果tofirst引數為false時則是下面滾洞配置
再看看start方法
start () {
if (this.direction === 'down') this.go(false) //對初始樣式方向
this.timer = setInterval(() => {
if (this.direction === 'up') {
this.currentIndex += 1
this.currenTranslateY = -this.currentIndex * this.height
} else {
this.currentIndex -= 1
this.currenTranslateY = -(this.currentIndex + 1) * this.height
}
if (this.currentIndex === this.length) {
setTimeout(() => {
this.go(true)
}, this.duration)
} else if (this.currentIndex === -1) {
setTimeout(() => {
this.go(false)
}, this.duration)
} else {
this.noAnimate = false
}
}, this.interval + this.duration)
},複製程式碼
start方法則是啟動方法if (this.direction === 'down') this.go(false)
//對初始樣式方向的第一個條目進行配置,如果是down,則是從最後一條開始,如果是up則是從第一條開始
2.開始定時器開始進行條止滾動如果沒有滾動到深度複製的dom的時候則一直開始動畫時長,如果下標配置到深度複製的dom條目時則傳入false進行go方法過度加入無逢滾動協條!改變translate3d的y方法
marquee.vue完整程式碼
<template>
<div class="vux-marquee" :style="{height: height + 'px'}">
<ul class="vux-marquee-box" ref="box" :style="{transform: `translate3d(0,${currenTranslateY}px,0)`, transition: `transform ${noAnimate ? 0 : duration}ms`}">
<slot></slot>
</ul>
</div>
</template>
<script>
export default {
props: {
interval: {
type: Number,
default: 2000
},
duration: {
type: Number,
default: 300
},
direction: {
type: String,
default: 'up'
}
},
beforeDestroy () {
this.destroy()
},
data () {
return {
currenTranslateY: 0,
height: '',
length: 0,
currentIndex: 0,
noAnimate: false
}
},
methods: {
destroy () {
this.timer && clearInterval(this.timer)
},
init () {
this.destroy()
if (this.cloneNode) {
this.$refs.box.removeChild(this.cloneNode)
}
this.cloneNode = null
let firstItem = this.$refs.box.firstElementChild //獲取box節點下的第一個元素
if (!firstItem) {
return false
} //如果沒有li元素則退出
this.length = this.$refs.box.children.length //獲得ul下li節點的長度
this.height = firstItem.offsetHeight
if (this.direction === 'up') {
this.cloneNode = firstItem.cloneNode(true)
this.$refs.box.appendChild(this.cloneNode)
} else {
this.cloneNode = this.$refs.box.lastElementChild.cloneNode(true)
this.$refs.box.insertBefore(this.cloneNode, firstItem)
}
},
start () {
if (this.direction === 'down') this.go(false) //對初始樣式方向
this.timer = setInterval(() => {
if (this.direction === 'up') {
this.currentIndex += 1
this.currenTranslateY = -this.currentIndex * this.height
} else {
this.currentIndex -= 1
this.currenTranslateY = -(this.currentIndex + 1) * this.height
}
if (this.currentIndex === this.length) {
setTimeout(() => {
this.go(true)
}, this.duration)
} else if (this.currentIndex === -1) {
setTimeout(() => {
this.go(false)
}, this.duration)
} else {
this.noAnimate = false
}
}, this.interval + this.duration)
},
go (toFirst) {
this.noAnimate = true
if (toFirst) {
this.currentIndex = 0
this.currenTranslateY = 0
} else {
this.currentIndex = this.length - 1 //當我們向下marquee的時候,此時最後一個下標為總長度-1
this.currenTranslateY = -(this.currentIndex + 1) * this.height
//因為如果向下的話,我們在li的最項部插入了最後一dom此時我們要+1
}
}
}
}
</script>
<style lang="less">
.vux-marquee {
width: 100%;
overflow:hidden;
}
.vux-marquee-box {
padding: 0;
margin: 0;
width: 100%;
height: auto;
li {
margin: 0;
width: 100%;
padding:10px 0;
box-sizing:border-box;
}
}
</style>複製程式碼
marquee-item配置
在components>marquee>marquee-item.vue
<template>
<li>
<slot></slot>
</li>
</template>
<script>
export default {
mounted () {
this.$nextTick(() => {
this.$parent.destroy()
this.$parent.init()
this.$parent.start()
})
}
}
</script>複製程式碼
當每個條目載入dom完畢則開始呼叫,如果是從新渲染,或者切換出去快取的元件則進行時間關畢,再進行Init()初始化,再start()開始滾動
App.vue
<template>
<div>
<marquee direction='down'>
<marquee-item class='bb' v-for="i in number" :key = "i">混無霹靂手-ziksang{{i}}</marquee-item>
</marquee>
</div>
</template>
<script>
import Marquee from './components/marquee/marquee.vue'
import MarqueeItem from './components/marquee/marquee-item.vue'
export default {
components: {
Marquee,
MarqueeItem
},
data () {
return {
number : 10
}
}
}
</script>
<style>
.bb{
font-size:20px;
}
</style>複製程式碼
然後你就可以啟動了,看看效果如何
渣渣前端開發工程師,喜歡鑽研,熱愛分享和講解教學, 微信 zzx1994428 QQ494755899
支援我繼續創作和感到有收穫的話,請向我打賞點吧
如果轉載請標註出自@混元霹靂手ziksang