做者 : 混元霹雳手-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