当前位置: 首页 > Web前端 > vue.js

深入VUE响应式原理(Vue数据更新了,但是页面显示旧数据)

时间:2023-03-31 17:54:14 vue.js

如何跟踪变化在项目中,数据更新了,但是页面没有更新或者显示旧数据。先简单解释一下响应式:响应式(即数据和页面显示同时更新)非响应式(即Vue中的数据更新了,但是页面显示还是旧数据)当你将一个普通的JavaScript对象作为数据选项传递给Vue实例时,Vue会遍历这个对象的所有属性,并使用Object.defineProperty将所有这些属性转换为getters/setters。Object.defineProperty是ES5中无法shimmed的特性,这也是Vue不支持IE8及以下浏览器的原因。这些getters/setters对用户是不可见的,但在内部它们允许Vue跟踪依赖项并在访问和修改属性时通知更改。这里需要注意的是,不同的浏览器在控制台打印数据对象时getter/setter的格式不同,所以建议安装vue-devtools以获得更友好的用户界面来查看数据。每个组件实例对应一个watcher实例,watcher实例会在组件渲染过程中记录“touched”数据属性作为依赖。然后,当依赖项的设置器触发时,观察者会收到通知,从而导致其关联的组件重新呈现。关于检测变化的注意事项由于JavaScript的限制,Vue无法检测数组和对象的变化。有一些方法可以绕过这些限制并使它们保持响应。对于对象,Vue无法检测属性的添加或删除。由于Vue在初始化实例时会对属性进行getter/setter转换,因此该属性必须存在于数据对象上,Vue才能将其转换为响应式。例如:varvm=newVue({data:{a:1}})//`vm.a`是响应式的(即数据和页面显示同时更新)**vm.b=2//`虚拟机。b`是无响应的(即Vue中的数据虽然更新了,但是页面显示的还是旧数据)。对于创建的实例,Vue不允许动态添加根级响应式属性。但是,可以使用Vue.set(object,propertyName,value)方法向嵌套对象添加响应式属性。比如对于:Vue.set(vm.someObject,'b',2)你也可以使用vm.$set实例方法,它也是全局Vue.set方法的别名:this.$set(this.someObject,'b',2)有时您可能需要为现有对象分配多个新属性,例如使用Object.assign()或_.extend()。但是,因此添加到对象的新属性不会触发更新。在这种情况下,您应该使用原始对象和要混合的对象的属性创建一个新对象。//而不是Object.assign(this.someObject,{a:1,b:2})this.someObject=Object.assign({},this.someObject,{a:1,b:2})Vue无法检测以下数组中的更改:当您直接按索引设置数组项时,例如:vm.items[indexOfItem]=newValue当您修改数组的长度时,例如:vm.items.length=newLength示例:varvm=newVue({data:{items:['a','b','c']}})vm.items[1]='x'//没有响应vm.items.length=2//没有responsive为了解决第一类问题,下面两种方式可以达到和vm.items[indexOfItem]=newValue一样的效果,同样会触发reactive系统中的状态更新://Vue.setVue.set(vm.items,indexOfItem,newValue)//Array.prototype.splicevm.items.splice(indexOfItem,1,newValue)也可以使用vm.$set实例方法,它是全局方法Vue的别名。set:vm.$set(vm.items,indexOfItem,newValue)为了解决第二类问题,可以使用splice:vm.items.splice(newLength)声明响应式属性由于Vue不允许动态添加根级响应属性,所以你必须在初始化实例之前声明所有根级响应属性,即使它只是一个空值:varvm=newVue({data:{//将消息声明为空字符串message:''},template:'

{{message}}
'})//然后设置messagevm.message='Hello!'如果你没有在data选项中声明message,Vue会警告你渲染函数正在尝试访问一个不存在的proprty