做者 : 混元霹靂手-ziksangjavascript
給vux打打廣告吧,我感受功能最強大的仍是vux ui庫,我帶你們看看這玩意如何實現的,你別看學別人寫組件,還能學到一些你日常用不到的弱知識點,雙擊,666666,沒毛病。前端
接下來仍是按着咱們約定的來vue
2.代碼運行vue-cli 2.1版本java
3.組件代碼都在components文件夾裏vue-cli
4.主代碼邏輯都在 App.vue文件夾裏緩存
我什麼都不要我只要微信
贊app
在vux中marquee裏分紅了兩組件,分別進行slotless
1.第一個組件中slot是用來放入每一個marquee節點
2.第二個組件中solt是在每一個節點放入文案dom
這有什麼好處呢?
1.第一可讓代碼更清楚,在第一個組進行邏輯層編寫和初始化配置
2.第二個組件進行邏輯啓動
這裏的無逢滾動又是如何作到的呢?
1.這裏進行了上滾動和下滾動,分別進行了不一樣的初始化配置
2.經過cloneChild(true)進行深複製分別辨別direction的位置進行配置
咱們先看看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