如果你发现自己需要在Vue中做一个强制更新,99.9%的情况下,你在某个地方做错了。1、Vue在创建实例时无法检测到数据中不存在的属性。原因:由于Vue会在实例初始化时对属性进行getter/setter转换,所以属性必须存在于数据对象上,Vue才能将其转换为响应式。的。场景:varvm=newVue({data:{},//页面不会改变template:'
{{message}}
'})vm.message='Hello!'//`vm.message`不是响应式解决方案:varvm=newVue({data:{//将a,b声明为空字符串message:'',},template:'{{message}}
'})vm.message='你好!'2.Vue无法检测对象属性的增删原因:官方-由于JavaScript(ES5)的限制,Vue.js无法检测对象属性的增删delete。因为Vue.js在初始化实例时会将属性转换为getters/setters,所以属性必须在数据对象上,以便Vue.js对其进行转换,使其具有响应性。Scene:varvm=newVue({data:{obj:{id:001}},//页面不会改变template:'{{obj.message}}
'})vm.obj.message='hello'//无响应deletevm.obj.id//无响应解决方案://动态添加-Vue.setVue.set(vm.obj,propertyName,newValue)//动态添加-vm.$setvm.$set(vm.obj,propertyName,newValue)//动态添加多个//而不是Object.assign(this.obj,{a:1,b:2})this.obj=Object.assign({},this.obj,{a:1,b:2})//动态移除-Vue.deleteVue.delete(vm.obj,propertyName)//动态移除-vm.$deletevm.$delete(vm.obj,propertyName)3.Vue无法检测到通过数组索引直接修改数组项原因:官方-由于JavaScript的限制,Vue无法检测到数组和对象的变化;游玉玺-性能成本与用户体验不成正比。场景:varvm=newVue({data:{items:['a','b','c']}})vm.items[1]='x'//不是响应式解决方案://Vue.setVue.set(vm.items,indexOfItem,newValue)//vm.$setvm.$set(vm.items,indexOfItem,newValue)//Array.prototype.splicevm.items.splice(indexOfItem,1,newValue)扩展:Object.defineProperty()可以监听数组的变化Object.defineProperty()可以监听数组的变化。但是给数组增加一个属性(索引)是不会检测到数据变化的,因为新增加的数组的下标(索引)是监听不到的,删除一个属性(索引)也是一样的。场景:vararr=[1,2,3,4]arr.forEach(function(item,index){Object.defineProperty(arr,index,{set:function(value){console.log('triggersetter')item=value},get:function(){console.log('triggergetter')returnitem}})})arr[1]='123'//triggersetterarr[1]//triggergetterreturnvalue"123"arr[5]=5//不会触发setter和getter4.Vue无法监听直接修改数组长度的变化原因:官方-由于JavaScript的限制,Vue无法检测到数组和对象的变化;游鱼溪-性能成本与获得的用户体验不成正比。场景:varvm=newVue({data:{items:['a','b','c']}})vm.items.length=2//不是响应式解决方案:vm.items。拼接(新长度)5。在执行异步更新之前,DOM数据不会发生变化。原因:Vue在更新DOM时异步执行。只要检测到数据变化,Vue就会打开一个队列,缓冲所有发生在同一个事件循环中的数据变化。如果同一个观察者被多次触发,它只会被推入队列一次。这种缓冲时的重复数据删除对于避免不必要的计算和DOM操作非常重要。然后,在下一个事件循环“tick”中,Vue刷新队列并执行实际(去重)工作。Vue内部尝试使用原生的Promise.then、MutationObserver和setImmediate来实现异步队列。如果执行环境不支持,它将使用setTimeout(fn,0)代替。场景: