问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

前端实现程序日志的自动滚动显示

发布网友 发布时间:2024-09-30 17:57

我来回答

1个回答

热心网友 时间:2024-12-14 23:19

一、需求

当某个程序在后端运行的时候,前端经常要显示一个动态的进度条,或者loading的动画,或者百分比的数字

当然,更好的效果是给当前的用户展示出程序运行的具体细节,比如运行中记录的日志,或者实时的进程环节

比如:

[12:01:59]正在启动应用进程[12:02:00]进程启动成功,正在获取网络资源...[12:02:01]成功启动下载任务[12:02:02]下载中....[12:02:03]下载成功,开始解析网络资源[12:02:04]正在安装相关程序[12:02:05]安装成功,应用进程结束

当然,这是我瞎写的,只是为了展示我们想要实现的日志的样子,当这样的日志内容或者进程内容很多的时候,最好的办法是随着内容的增加,让页面自动向下滚动,方便用户查看最新的消息

二、分析

在这个过程中,一方面要不断的调用接口来获取最新的数据,一方面还要把数据渲染到页面中,同时让页面发生滚动

注意这里要让页面产生滚动的动画,有三个条件

不能每次接口都返回全量数据直接替换页面数据,这样会导致页面没有滚动的动画

页面的css样式要正确设置,确保内容只在父元素的可视区域内发生滚动而不是整个页面滚动

使用正确的API来完成滚动的效果

三、实现方法

第一个条件是很好的做的,我们可以使用setInterval

vartimer=setInertval(()=>{getLogList().then(res=>{randerView(res.data)})},2000)

不过这样做有个弊端,就是当用户网络不那么畅通,或者服务器比较拥挤的时候,已经调用的接口一直处于pendding的状态,后面的接口还在持续不断的调用,会让本就拥堵的服务雪上加霜

所以我更喜欢使用setTimeout

asyncfunctiongetLogData(){constlogData=awaitgetLogList()randerView(logData.data)setTimeout(getLogData,2000)}getLogData()

第二个样式问题,只需要正确的给父元素添加固定的高度和overflow-y:scroll就可以了。

下面来说说第三个问题,如何让内容自动的向下滚动,因为这部分是比较重点的内容,我就单独放一个小节里来说

页面自动滚动的方案探讨

一般来说,如何让内容自动的向下滚动有两种方法来实现。

scrollIntoView

scrollIntoView方法会滚动元素的父容器,使调用scrollIntoView的元素在父元素中可见。

语法如下:

element.scrollIntoView();//等同于element.scrollIntoView(true)element.scrollIntoView(alignToTop);//Boolean型参数element.scrollIntoView(scrollIntoViewOptions);//Object型参数

参数说明:参数类型默认值备注alignToTopbooleantrue该元素的顶端是否和其所在滚动区的可视区域的顶端对齐scrollIntoViewOptionsobject{behavior:"auto",block:"start",inline:"nearest"}behavior:定义滚动动画过度,可选auto、smooth;block:定义垂直方向的对齐,可选start,center,end,或nearest;inline:定义水平方向的对齐,可选start,center,end,或nearest使用方法:<template><div><strong>进程日志</strong><divstyle="max-height:120px;position:relative"><divv-if="logs.length"><pv-for="(item,index)inlogs":key="index":id="(logs.length===index+1)?'scollLog':''">{{item}}</p></div><pv-else>暂无数据</p></div></div></template><script>import{Component,Vue,Watch,Prop}from'vue-property-decorator'import{formatTime}from'@/utils'@ComponentexportdefaultclassextendsVue{@Prop()privateLOGS:Array<object>;privatename:string='processLog';privatelogs:Array<string>=[];//getData将父组件传递过来的日志转成`[12:01:59]正在启动应用进程`这种格式privategetData(){this.logs=this.LOGS?this.LOGS.map((item:object):string=>'['+formatTime(item.updatedTime)+']'+item.content+'\n'):[]}@Watch('LOGS')scrollLogs(newValue){this.getData()//在日志渲染之后,将最底下的日志滚动到其父元素可视区域内this.$nextTick(()=>{if(newValue.length!==0){(document.getElementById('scollLog')asHTMLElement).scrollIntoView({behavior:'smooth',block:'nearest'})}})}mounted(){this.getData()}}</script><stylescoped>.logList-item{padding:8px0;margin:0;}</style>总结

scrollIntoView这个方法的对iossafari和IE不是很友好,其他的浏览器没有什么问题

另外,这个方法对布局也没有什么要求,简单方便又易于理解,只需要针对最后一条渲染的日志调用即可

scrollTo

这个方法是老生常谈了,这个方法可把内容滚动到指定的坐标。

语法如下:

scrollTo(xpos,ypos)

参数说明:参数类型默认值备注xposnumber-必需。要在窗口文档显示区左上角显示的文档的x坐标yposnumber-必需。要在窗口文档显示区左上角显示的文档的y坐标使用方法:<template><div><divref="consoleWindow"><divid="console_output"ref="consoleOutput"><--这里写日志信息,注意,一定要在父元素外再套一层--></div></div></div></template><script>import{Component,Vue,Watch,Prop}from'vue-property-decorator'import{post}from'@/utils/http'@ComponentexportdefaultclassextendsVue{asyncgetData(){constres=awaitpost(`/api/get/log`,{read:true})this.formatData(res.data)}formatData(data){try{if(data.length){data.forEach(item=>{this.printLine('['+item.updateTime+']'+item.value)})}else{this.printLine('暂无数据','input_line')}}catch(e){console.log('error')}}printLine(s,type){if((s=String(s))){letn=document.createElement('pre')if(!type)type='output_line'if(n.innerText!==undefined){//IEhastouseinnerTextn.innerText=s}else{//FirefoxusescreateTextNoden.appendChild(document.createTextNode(s))}n.className=typethis.$refs.consoleOutput.appendChild(n)//添加完日志后,让父元素滚动到其自身的距离this.$refs.consoleWindow.scrollTop=this.$refs.consoleWindow.scrollHeight}}mounted(){this.getData()}}</script><stylescoped>.console-wraper{display:flex;flex-direction:column;height:100%;}.console_window{flex:1;background:#333;overflow:auto;.console_output{white-space:pre-wrap;word-wrap:break-word;padding:12px;font-weight:bold;}/deep/pre.input_line{font-size:14px;color:yellow;opacity:0.8;padding:020px;}/deep/pre.output_line{color:#fff;font-size:13px;white-space:pre-wrap;word-wrap:break-word;padding-left:40px;opacity:0.7;}}</style>

本文的内容到此就结束了,案例代码未经完整测试,有任何问题可以在评论区留言哦:)

作者:晴天同学

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
豆瓣酱放多了怎么补救 鑫创sssbd量产工具 为了了解某校1500名学生的体质状况,随机调查了这个学校内一定数量学生... 564÷85的竖式如何列? 上海房屋过户 要准备什么资料 个人卖房要提供哪些资料 房屋交易资料需要哪些 房子买卖要哪些资料 房产交易需要什么资料 ...让重锤自由下落,打出的一条纸带如图所示,图中 ...而且在这个路口很爱出车祸,怎么能改善房子的... keep-alive中使用show-overflow-tooltip切换路由tooltip不消失的解决... 什么叫财产综合险 ...但是毕业证大概是得在考研现场确认之后才能拿到 可以考研吗_百度知 ... 毛坯房装修步骤和流程,花小钱装好家 有木有重生到鹦鹉的小说 梦见闺密得精神病,在路上追赶别人,还来家里找我玩,头发乱糟糟的... 万用表品牌排行榜是怎么样的 怎么从电脑配置看显卡是N卡还是A卡。 笔记本电脑显卡是N卡还是A卡? 去照相管里洗盘里的照片七寸的多少钱 英军为JW—61船队精心组织了怎样的护航力量? 南京秦淮区景区景点推荐图片 王者如何删除游戏好友功能 TIKTOK中文出海的哪些大咖主播?为什么风格近似 剑网3隐元会东篱寨的日常任务都在哪接啊 夜尿多是怎么 草鱼剁椒鱼的做法剁椒鱼的做法 ...从未做过抽血检查。我现在怀疑他已经患尿毒症。他夜尿多,但尿... 《剑网3》长安内城声望获取日常任务介绍_《剑网3》长安内城声望... qq秀里,不小心点了收藏,怎样删除掉“我的收藏”里的装扮啊? got7 成员每个家境都有很好吗 生气会影响八个身体器官的健康 生气对身体哪个器官伤害最大 苹果手机短信删除了,短信标志上还有数字怎样去掉 护士资格证提前多久变更 ...Citizenship in Every National Case of Emergenc是什吗意思_百度知... 护士执业证变更需要多长时间 陕西和甘肃为什么不亲 相亲怎么开始聊天刚相亲的女孩怎么聊天 我想在网上买火车票 不知道是怎么个流程 怎么到我手里 是快递公司给送... 跟刚相亲的女孩子怎么聊天 相亲认识的女生怎么聊天 跟相亲的女孩聊天技巧 和相亲女孩聊天怎么找话题 how can i get to是什么意思 ...日中共中央政治局会议强调要下大决心改进作风切实解决什么的问_百度... 应该是could you tell me how can I get to还是how I can get to_百度... 我电脑在学校于江西工业职业技术学院宿舍4月12日被盗 求推荐好看的Gl漫画啊。。。 梅州火龙果