vue数据渲染

今天遇到一个小问题,又是关于vue数据渲染的。
在这里插入图片描述
选中模块分类时,带出业务类型大类的数据。但是写完之后数据没有带出,打印跟使用vue-devtools调试发现数据已经渲染,就明白又是数据渲染的问题。但是以前遇到这种问题,一般是对象或数组进行深层次的嵌套才会出现,这次就一个空对象,searchDataList: {}竟然也出现了这种问题。

先不慌,这种问题遇到了很多次,解决办法也有问多。
首先贴上简写的代码:

getChildMedia() {
	this.searchDataList.mediaBigCategory = []
	if(模块分类数据存在时) {
		req.get(模块分类).then(res => {
			this.searchDataList.mediaBigCategory = res
		})
	}
}
1.this.$set()

首先使用了this.$set(),这是最便捷最常用的方法。对于这个用法,官方的解释是

向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = ‘hi’)

所以我将代码修改成:

getChildMedia() {
	this.searchDataList.mediaBigCategory = []
	if(模块分类数据存在时) {
		req.get(模块分类).then(res => {
			this.$set(this.searchDataList, 'mediaBigCategory', res)
			//this.searchDataList.mediaBigCategory = res
		})
	}
}

事实证明毫无效果。

2.this.$nextTick()

这也是一种常用方法,先来看下官方解释:

将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

然后我将代码修改为

getChildMedia() {
	this.searchDataList.mediaBigCategory = []
	if(模块分类数据存在时) {
		req.get(模块分类).then(res => {
			this.$nextTick(() => {
				this.searchDataList.mediaBigCategory = res
			})
		})
	}
}

实时证明依旧无效!

3.this.$forceUpdate()

这是一种不太常用方法,看下官方解释:

迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

修改代码如下:

getChildMedia() {
	this.searchDataList.mediaBigCategory = []
	if(模块分类数据存在时) {
		req.get(模块分类).then(res => {
			this.searchDataList.mediaBigCategory = res
			this.$forceUpdate()
		})
	}
}

这次惊奇的发现成功了!之前遇到这种渲染问题都是这三个办法依次试试,这次就来找找原因出在哪。

查找原因

首先仔细看看官方文档对于这三个方法的解答。
首先是this.$set()请添加图片描述

可以看出该方法是在响应对象里面添加一个响应对象,并且触发视图更新,看似跟我们需求很符合,但是看看我们的代码发现,我们在最开始的使用为了让他请清空而写了一行代码:this.searchDataList.mediaBigCategory = [],也就是说在我们使用this.$set(this.searchDataList, 'mediaBigCategory', res)的时候,searchDataList属性里面已经存在了mediaBigCategory属性,并且官方说了普通方法添加属性是无法被检测,这就是this.$set()失效的原因。想到这里我们应该已经知道怎么修改了
修改后代码

getChildMedia() {
	this.$set(this.searchDataList, 'mediaBigCategory ', res)
	this.searchDataList.mediaBigCategory = []
	if(模块分类数据存在时) {
		req.get(模块分类).then(res => {
			this.searchDataList.mediaBigCategory = res
		})
	}
}

修改完成后,发现已经可以进行数据渲染。

既然$set可以,那$nextTick呢?
仔细阅读官方解释可以明白,这个方法会将你的操作放进一个回调函数里面,然后等DOM更新完成,执行回调函数。那么我们使用普通方法this.searchDataList.mediaBigCategory = []添加的属性是不算响应属性的,也就不会进行DOM更新,所以无论怎样,数据都不会进行渲染。
该方法主要是避免vue的覆盖机制:例如当一个属性被连续修改多次,vue是不会多次渲染的,为了节省性能,会只渲染最后一次,而nextTick就可以让你在渲染多次的过程中进行一些操作。

既然$nextTick不行,那$forceUpdate为什么可以呢?
咱们同样从官方文档里找答案。该方法会使整个vue实例重新渲染!也就是说整个页面相当于重新渲染过,而渲染时,数据是不会丢失的,就相当于重新渲染的时候mediaBigCategory 属性最开始就存在于searchDataList对象里,数据自然也就会被渲染出来。

注意的时,虽然使用forceUpdate可以将数据渲染出来,但并不会将非响应属性改为响应属性,也就是说你修改mediaBigCategory 属性依旧不会进行重新渲染,必须再次进行forceUpdate

补充

除了上面的几个方法外还有一个更简单的方法,就是给data里面的对象里面的属性默认值。例如

searchDataList: {
	mediaBigCategory: []
}

这样在数据一开始进行渲染就会自动将mediaBigCategory渲染成响应属性,自然修改的时候也就会跟着渲染。

总结

说到最后,还是官方文档解决了所有问题!虽然每个方法就一两句话,但绝对不多一句废话,不少一句要点。官方文档,yyds!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值