最近开发前段项目,遇到公司项目需求,要求字体滚动展示。
为了实现快速开发,便开始寻找现成代码,看来看去,要么是不符合项目需求,要么就是原生,老长一串代码,看着看着就emo了。于是决定自己开始动手写适合项目的需求逻辑。
***
<template>
<div class="WarningRealTime">
<div class="WarningRealTime-title">实时预警</div>
<div class="WarningRealTime-body">
<div class="body-title">
<div>安全员名称</div>
<div>预警分类</div>
<div>预警时间</div>
</div>
<div style="width: 36rem; overflow: hidden" v-if="datalist.length">
<div ref="body" @scroll="bodyscroll" style="width: 36.8rem; height: 17.5rem; overflow: auto; padding: 1% 0">
<div class="body" v-for="item in datalist" :key="item.gettime">
<div>{{ item.realname }}</div>
<div>{{ item.dangerType }}</div>
<div>{{ item.gettime }}</div>
</div>
</div>
</div>
<img class="nodata" v-else src="@/assets/nodata.png" alt="" />
</div>
</div>
</template>
<script>
import { hazardRealTime } from '@/api/manage'
export default {
//实时预警
name: 'WarningRealTime',
props: ['SiteId'],
data() {
return {
//这个datalist是存储请求接口后返回的数据
datalist: [],
scrllotop: 1,
scrlloheight: 0,
time: '',
index: 0,
domindex: 0,
}
},
mounted() {
//页面加载完成请求数据
this.getdatainit()
//设置定时器500ms
this.time = setInterval(() => {
// 上来就先增值
this.scrllotop = this.scrllotop + 10
// 如果index所累加的次数等于datalist的下标则让index等于0,它主要作用于数组datalist的下标
if (this.index == this.datalist.length - 1) {
this.index = 0
} else {
//否则index则继续累加
this.index++
}
//此变量主要用于以下的条件过滤
this.domindex++
//使用模板字符串创建一个需要且符合你项目的格式一定要注意appendChild和vue的v-html的区别,appendChild不会清除之前的节点,而v-html会将之前的节点全部清空,不合符项目字体滚动使用的逻辑
let childdom = `${this.datalist[this.index].realname}
${this.datalist[this.index].dangerType}
${this.datalist[this.index].gettime}`
//再次创建一个div标签,此处注意,一定要创建,如果还是使用childdom样的模板字符串只会生成字符串类型,使用document.createElement生成的则是dom节点流,是对象类型,且这是每一条的父标签,则直接使用innerHtml加入到父标签内就行了,剩下的交给浏览器去渲染
var dom = document.createElement('div')
dom.style.border = ' none'
dom.style.width = '90%'
dom.style.margin = ' 2% auto'
dom.style.display = 'flex'
dom.style.justifyContent = 'space-around'
dom.style.fontSize = '0.75rem'
dom.style.textAlign = 'center'
dom.innerHTML = childdom
//每次定时器触发,就检查一遍domindex 变量是否等于5,此处随自己设置的滚动窗口设置,如果窗口较大,也可以设置较大一点,每添加五次,则removeChild删除一次节点,直到符合自己的效果就行
this.$nextTick(() => {
if(this.domindex == 5){
this.$refs.body.removeChild(this.$refs.body.children[0])
this.domindex = 0
}
//然后再将新创建的数据插入到滚动窗口的底部
this.$refs.body.appendChild(dom)
//将当前滚动窗口的属性scrollTop 赋值
this.$refs.body.scrollTop = this.scrllotop
//赋值之后,再将当前滚动条的高度赋值给变量,确保下次累加数据跟得上
this.scrlloheight = this.$refs.body.scrollTop
})
}, 500)
},
watch: {
SiteId() {
this.getdatainit()
},
},
methods: {
async getdatainit() {
let { success, code, result } = await hazardRealTime({ constructionId: this.SiteId })
if (success && code == 200) {
this.datalist = result
}
},
bodyscroll(e) {
// console.log(e);
},
},
//当前页面的定时,要做到,有使用,离开页面必销毁,不然定时器多了浏览器的负担会增大
destroyed() {
clearInterval(this.time)
this.time = ''
},
}
</script>
<style lang="less" scoped>
.WarningRealTime {
flex: 1;
padding: 0.8% 1%;
background: url('../../../../../../assets/img/AI-border1.png') round;
color: #fff;
.WarningRealTime-title {
width: 30%;
height: 10%;
margin: 0 auto;
text-align: center;
color: #23cefd;
font-size: 1rem;
font-weight: bold;
font-size: 1rem;
font-weight: bold;
background: url('../../../../../../assets/img/Ai-title.png') round;
}
.WarningRealTime-body {
width: 100%;
height: 19rem;
overflow: hidden;
//此处的设置,看个人项目,如果需要滚动条的则把ref="body"的父元素标签放大漏出来就行,或者直接去掉他的父元素标签,如果为了美观不需要显示滚动条的,则直接根据对应的宽度overflow: hidden隐藏掉滚动条就行
.body,
.body-title {
width: 90%;
margin: 0 auto;
border-bottom: 1px solid #23cefd;
display: flex;
justify-content: space-around;
color: #23cefd;
font-size: 12px;
text-align: center;
div {
flex: 1;
}
}
.nodata {
width: 16rem;
margin-left: 28%;
margin-top: 10%;
}
.body {
border: none;
margin-top: 2%;
div {
color: #fff;
}
div:nth-of-type(2) {
color: red;
}
}
}
}
</style>
此方法的滚动不是很线性,如果有使用的请进行二次编写
这是一个模块,可以直接使用
逻辑:先将第一个显示的宽高等于0,会出现隐藏效果,或者先将第一条的dom的display设置none,先隐藏掉,来达到目的,这个因为不需要滚动条所以不用给父元素上加宽遮盖,这个会消失一个添加一个
<template>
<div class="carousel">
<div v-if="lists.length" ref="carousel">
<div v-for="item in lists" class="carousel-row" :key='item.tag'>
<a target="view_window" :href="item.documentPathUrl" :title="item.name"
><span>【 {{ item.tag }} 】</span>
{{ item.name.length > 30 ? item.name.slice(0, 30) + ' . . .' : item.name }}</a
>
</div>
</div>
<img class="nodata" v-else src="@/assets/nodata.png" alt="" />
</div>
</template>
<script>
export default {
name: 'HelmetUiCarousel',
props: ['lists', 'config'],
data() {
return {
total: 0,
dataitem: [],
time: '',
}
},
watch: {
lists(newval) {
console.log(newval)
if (this.config.state) {
this.animation()
}
},
},
mounted() {
console.dir(this.$refs.carousel)
// setInterval
},
methods: {
animation() {
//上来先定时器
this.time = setInterval(() => {
//思路和上边项目差多,先对比条数
if (this.total >= this.lists.length - 1) {
//达到条件赋值为0
this.total = 0
} else if (this.total < this.lists.length - 1) {
//否则则进行自加
this.total++
}
//先设置子节点的第一条宽高为0
this.$refs.carousel.children[0].style.height = '0px'
this.$refs.carousel.children[0].style.lineHeight = '0px'
//再删除子节点的第一条
this.$refs.carousel.removeChild(this.$refs.carousel.children[0])
//创建一个新的div
let dom = document.createElement('div')
//宽高和v-for渲染的一致,否则后边插入的会出现视觉上不对称
dom.style.height = '2.05rem'
dom.style.lineHeight = '2.05rem'
//模板字符串的变量
let span = `【 ${this.lists[this.total].tag} 】`
//因为此处需要外链,所以使用creatrElement创建的a标签
let a = document.createElement('a')
a.target = 'view_window'
a.href = this.lists[this.total].documentPathUrl
a.innerHTML = `${span} ${
this.lists[this.total].name.length > 30
? this.lists[this.total].name.slice(0, 30) + ' . . .'
: this.lists[this.total].name
}`
//后边开始俄罗斯套娃,一个套一个
dom.appendChild(a)
this.$refs.carousel.appendChild(dom)
}, this.config.time)
},
},
//最后还是页面离开销毁
destroyed() {
clearInterval(this.time)
this.time = 0
},
}
</script>
<style lang="less" scoped>
.carousel {
width: 100%;
height: 100%;
overflow: hidden;
.carousel-row {
height: 2.05rem;
line-height: 2.05rem;
// border:1px solid green;
span:nth-of-type(1) {
color: #02c1d7;
}
}
.nodata {
width: 16rem;
margin-left: 30%;
margin-top: 10%;
}
}
</style>