Vue渲染失败的几种原因和解决方法
在进行数据双向绑定中,常遇到当数据变了,页面却没有同步渲染的情况。首先Vue 的数据双向绑定原理 是分为1.observe2.deps3.watcher在observe中,会通过Object.keys()获取所有的属性push一个订阅器到 deps中,1.假设template中,我在created的钩子函数中定义了this.a = 1,在btn中添加了事件改变this.a,此时观察到页面未渲染。&
在进行数据双向绑定中,常遇到当数据变了,页面却没有同步渲染的情况。
首先Vue 的数据双向绑定原理 是分为
1.observe
2.deps
3.watcher
在observe中,会通过Object.keys()获取所有的属性push一个订阅器 到 deps中,
一.假设template中,我在created的钩子函数中定义了this.a = 1,在btn中添加了事件改变this.a,此时观察到页面未渲染。
<template>
<div>{{a}}
<button @click="fnbtn">点击</button>
</div>
</template>
原因:Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data
对象上存在才能让 Vue 将它转换为响应式的。
解决:
在data中定义属性a,此时点击按钮页面会进行同步渲染。
data(){
return{
a:1
}
},
二.因为Vue无法检测到属性的添加和移除,所以以下操作,页面也没办法同步渲染。
<template>
<div>
<p v-for="(value,key) in obj">
{{value}}
</p>
<button @click="fnbtn">点击</button>
</div>
</template>
data(){
return{
obj:{
a:1,
b:2
}
}
},
fnbtn(){
this.obj.c = 3
},
解决:1.在data中obj默认生成定义一个c, obj:{ a:1, b:2,c:' ' }直接渲染的话,会渲染出一个空的dom元素,所以最好在computed中进行下处理
computed:{
objFilter(){
let newObj = JSON.parse(JSON.stringify(this.obj))
for(let key in newObj){
if(!newObj[key]){
delete newObj[key]
}
}
return newObj
}
},
2.上述方式比较麻烦,Vue提供了原生的方法处理 该方法可以向向嵌套对象添加响应式 property。
this.$set(this.obj,'c',3)
3.若是要删除属性b,采用直接 this.obj.b = ' '的方式,但是最好能结合下计算属性的方法避免生成无用的标签。除此之外,Vue采用了另一种方法也可以达到想要的效果
this.obj = Object.assign({}, { a: 1})
相当于重新为obj指向了新的对象,此时查看控制台也没有空的标签产生。
三. 对于数组,当你直接去改变arr[i]的某个值时,并不会触发响应渲染
<p v-for="i in arr">
{{i}}
</p>
this.arr[0] = 8 //此时数组确实改变了,但是不会触发响应渲染。
原因:
Vue 不能检测以下数组的变动:
- 当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
解决:
1.采用上述this.$set方法
this.$set(this.arr, 0, 8) //因为数组也可以理解成key为索引的对象 {0:1,1:2,2:3,3:4}
2.采用splice
splice(indexOfItem, 1, newValue)
以下方法操作数组都可触发响应,直接给数组重新赋值也可以触发响应 (this.arr = newArr)
1.push()
2.pop()
3.shift()
4.unshift()
5.splice() 拼接
6.sort() 将…分类
7.reverse() 颠倒 反转
以上就是容易导致渲染出错的几种情况和解决方法,当数据发生改变而页面没有渲染的时候,要分析是数据响应的哪一步出现了问题。
扩展:异步更新(就是当数据发生改变还没有渲染到dom的时候,此时去获取那个dom元素的值是旧的值)
可以用 this.$nextTick(fn(){})来获取新的值
this.$nextTick(fn(){})返回一个Promise对象,所以可以结合async await结合使用
更多推荐
所有评论(0)