当动态渲染页面时,如何判断页面的DOM节点已经渲染完成?

vue 有一个重要的概念:异步更新队列。Vue在观察到数据时并不是直接更新DOM,而是开启一个队列,并缓冲在同一个事件循环中发生的所有数据变化。在缓冲时会去除重复数据,从而避免不必要的计算和DOM操作。
官网教程地址:https://cn.vuejs.org/v2/guide/reactivity.html
如下:通过websocket方式接受了后端的数据,并在页面渲染了几个图标。如果要获取第一个图标,并将其颜色变蓝,如果不使用 n e x t T i c k ( ) 方 法 , 会 报 错 : c a n n o t r e a d p r o p e r t y s t y l e o f n u l l 。 因 为 此 时 节 点 还 没 有 渲 染 完 成 , 通 过 I D 去 获 取 D O M 节 点 获 取 到 的 是 N u l l 。 当 使 用 了 nextTick()方法,会报错:cannot read property style of null 。因为此时节点还没有渲染完成,通过ID去获取DOM节点获取到的是Null。当使用了 nextTick():cannotreadpropertystyleofnullIDDOMNull使nextTick()方法后,会等页面的DOM节点渲染完成后才执行其中的代码。使用$nextTick就是确保我们操作的是更新后的DOM。

<template>
	<div class="home">
		<div v-if="ifShow" class="openning">开启消灭小怪兽之旅吧</div>
		<div v-else>
			<div class="center title">
				<p v-text="title" @click="flowWebsocket()"></p>
				<!--<label v-text="title"></label>-->
			</div>
			<div class="center flow">
				<!--<div class="icon iconfont icon-gaojing"></div>-->
				<div v-for="item in imgs" :id="item.id">
					<!--<img :src="item.imgSrc"/>-->
					<span :class="item.imgSrc">
				</span>
					<h3>{{item.subTitle}}</h3>
				</div>
			</div>
			<div class="center content" ref="done">
				<iframe :src="contentSrc" frameborder="0" v-if="isUrl"></iframe>
				<div v-else>
					<span class="icon iconfont icon-wanchenggouxuan multiColor"></span>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
	import SockJS from "sockjs-client";
	import Stomp from "stompjs";
	import con1 from "../assets/logo.png";
	import con2 from "../assets/check-circle.png"
	export default {
		name: "home",
		data() {
			return {
				title: '',
				//items罗列所有的图标和相应的标题
				items: {
					imgSrc: "icon iconfont icon-web-icon-",
					subTitle: '默认'
				},
				imgs: [],
				contentSrc: '',
				isUrl: true,
				stompClient: null,
				url: 'http://10.88.44.46:8080/imc',
				ifShow: true
			}
		},
		methods: {
			init() {
				var socket = new SockJS(this.GLOBAL.httpUrl + "/ws");
				this.stompClient = Stomp.over(socket);
			},
			initWebsocket() {
				var monster = null;
				var steps = [];
				var id = '';
				var firstId = '';
				var imgSrc = '';
				var subTitle = '';
				var url = '';
				var socket = new SockJS("http://10.88.44.142:8080/ws");
				var stompClient = Stomp.over(socket);
				stompClient.connect({}, function(frame) {
					stompClient.subscribe('/topic/global', function(message) {
						//						this.listData = JSON.parse(message.body);
						//						console.log('date', this.getCurrentDate(2));
						//message为一个数组,传递流程各环节的名称
						//						console.log('message1', message);
						//						console.log('message', message.body);
						this.ifShow = false;
						monster = JSON.parse(message.body);
						//						console.log('steps', monster.stepIds);
						steps = monster.stepIds;
						//						this.title = monster.name;
						this.title = "数据库表空间自动化扩充流程";
						this.imgs = [];
						//渲染整体流程
						steps.forEach(step => {
							if(step.showType == 0) {
								id = step.id;
								imgSrc = (step.icon == null) ? this.items.imgSrc : step.icon;
								subTitle = (step.name == null) ? this.items.subTitle : step.name;
								this.imgs.push({
									'id': id,
									'imgSrc': imgSrc,
									'subTitle': subTitle
								});

								//取得第一个需要展示的url展示在页面下方
								if(url == '') {
									firstId = step.id;
									url = (step.url == null) ? this.url : step.url;
									//									url = "http://10.88.44.67:8080/imc/loginCmd.jsf?name=admin&simplePwd=admin&navigation=/fault/browser/faultInfo.jsf?beanName=faultQueryBean&faultId=0";
									console.log("url-" + url);
									this.contentSrc = url;
								}
							}
						});
						//this.nextTick() 中的代码会等待页面中的DOM节点都渲染完成后才会触发
						this.$nextTick(() => {
							//渲染下方展示图片
							console.log('需要渲染的divID为', firstId);
							console.log('element-', document.getElementById(firstId));
							document.getElementById(firstId).style.color = "#4EC0FF";
							document.getElementById(firstId).style.borderBottom = "2px solid #4EC0FF";
						});

					}.bind(this));
				}.bind(this));

			},
			flowWebsocket() {
				var socket = new SockJS("http://10.88.44.142:8080/ws");
				var stompClient = Stomp.over(socket);
				var titles = [];
				var id = '';
				var step = null;

				stompClient.connect({}, function(frame) {
					stompClient.subscribe('/topic/step', function(message) {
						console.log('message-', message);
						console.log('date', this.getCurrentDate(2));
						this.imgs.forEach(step => {
							//							debugger;
							document.getElementById(step.id).style.color = "#808891";
							document.getElementById(step.id).style.borderBottom = "2px solid white";
						});
						//id = message.id;
						step = JSON.parse(message.body);
						id = step.id;
						console.log('id-', id);
						document.getElementById(id).style.color = "#4EC0FF";
						document.getElementById(id).style.borderBottom = "2px solid #4EC0FF";
						console.log("目前的流程节点-", document.getElementById(id));
						this.contentSrc = (step.url == null) ? this.url : step.url;
						if(id == "5") {
							this.isUrl = false;
							this.$refs.done.style.height = "0vh";
							this.$refs.done.style.backgroundColor = "#F7F8FA";
							this.$refs.done.style.color = "#2EA40D";
						}
					}.bind(this));
				}.bind(this));
			},
			test() {
				var titles = ['ITSM工单系统', '自动化执行', '完成'];
				console.log('titles', titles)
				var num = 1;
				var id = '';
				titles.forEach(title => {
					id = title + num;
					this.items.forEach(item => {
						if(title == item.subTitle) {
							this.imgs.push({
								'id': id,
								'imgSrc': item.imgSrc,
								'subTitle': item.subTitle
							})
						}
					})
				})
			},
			getCurrentDate(format) {
				var now = new Date();
				var year = now.getFullYear(); //得到年份
				var month = now.getMonth(); //得到月份
				var date = now.getDate(); //得到日期
				var day = now.getDay(); //得到周几
				var hour = now.getHours(); //得到小时
				var minu = now.getMinutes(); //得到分钟
				var sec = now.getSeconds(); //得到秒
				month = month + 1;
				if(month < 10) month = "0" + month;
				if(date < 10) date = "0" + date;
				if(hour < 10) hour = "0" + hour;
				if(minu < 10) minu = "0" + minu;
				if(sec < 10) sec = "0" + sec;
				var time = "";
				//精确到天
				if(format == 1) {
					time = year + "-" + month + "-" + date;
				}
				//精确到分
				else if(format == 2) {
					time = year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec;
				}
				return time;
			}
		},
		mounted() {
			this.initWebsocket();
			//			this.test();
			this.flowWebsocket();
		}
	}
</script>
<style lang="css" scoped>
	@import url("../assets/icon/iconfont.css");
	.center {
		/*border: 1px solid red;*/
		margin: auto;
		width: 90vw;
		text-align: center;
	}
	
	.title {
		/*height: 10vh;*/
		padding: 0vh 0vh 0vh 0vh;
		font-size: 3vw;
		margin-top: 3vh;
		margin-bottom: 2vh;
	}
	
	.flow {
		/*border: 1px solid blue;*/
		height: 15vh;
	}
	
	.flow span {
		font-size: 4vw;
	}
	
	.multiColor {
		background: -webkit-linear-gradient(left bottom, #2CA10A, #5BEE4C);
		font-size: 15vw;
	}
	
	.icon-wanchenggouxuan {
		-webkit-background-clip: text;
		-webkit-text-fill-color: transparent;
	}
	
	.flow p {
		font-size: 6vw;
	}
	
	.flow div {
		/*color: #4EC0FF;*/
		color: #808891;
		/*border-bottom: 2px solid #808891;*/
		padding-right: 5vw;
		padding-left: 5vw;
		margin-left: 1vw;
		display: inline-block;
	}
	
	iframe {
		width: 90vw;
		height: 70vh;
	}
	
	.content {
		margin-top: 1vh;
		/*border: 1px solid green;*/
		height: 70vh;
	}
	
	.content div {
		font-size: 10vw;
		background-color: #F7F8FA;
		padding: 15vh;
	}
	
	.openning {
		padding: 40vh 0vh;
		font-size: 60px;
		font-weight: bold;
		background: -webkit-linear-gradient(left,red,orange,yellow,green,blue,indigo,violet);
		-webkit-background-clip: text;
		-webkit-text-fill-color: transparent;
	}
</style>
Logo

前往低代码交流专区

更多推荐