今天要讲的内容是Web前端框架vue.js中的一个细节,注意是细节哦,稍不留神就掉坑里了。
由于这两天在公司开发前端vue页面,踩到了一个坑,这个坑不大不小的,但是对于我这种除非公司需要,否则不会主动学习前端技术的后端开发者来说,这个坑困扰了我半天时间。无论怎么修改代码,还是实现不了效果,归根结底还是没有找到问题的点所在。
凡事都有好的一面,今天上午脑子就开了光,思路比昨天下午清晰多了,顺着思路,我终于发现了问题的点所在,然后百度一搜,果然是这样,嗨!于是我决定总结一番!
大家都知道,vue的核心特性是数据动态双向绑定,但是数据绑定背后的原理是什么呢,这个有必要了解一番。
当你将一个普通的js对象作为vue的数据时,vue会遍历该对象的所有属性,并通过Object.defineProperty()方法将这些属性全部转化为getter/setter。defineProperty()是js标准内置对象Object的一个方法,用于直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。这句话有点抽象,先来看一下该方法的语法。
Object.defineProperty(obj, prop, descriptor)
属性描述符有以下可选方案:
通过上面的介绍,我们了解到了Object.defineProperty()方法可以这么用。
Object.defineProperty(user, "name", {get() { return value; }, set(newValue) { value= newValue; }, configurable : true, value: "小明" });
关于Object.defineProperty()更深层次的介绍请戳这里 Object.defineProperty() – JavaScript | MDN
Object.defineProperty()说完了,接下来继续聊聊vue的响应式原理。前面说到Object.defineProperty()方法将这些属性全部转化为getter/setter,而这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。这种关系可以用下图表示。
说完了上面的vue核心原理,下面聊聊标题:vue不能动态监测对象属性的问题!
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。一听到这,是不是觉得没法玩了?不要慌,问题总是有解决办法滴!下面就聊聊解决办法!
Vue 无法检测 property的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在对象上存在才能让 Vue 将它转换为响应式的。例如:
对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如:
var vm = new Vue({
data:{
a:1
}
});
//vm.a是响应式的
vm.b = 2
//vm.b是非响应式的
对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如:
Vue.set(vm.someObject, 'b', 2)
您还可以使用 vm.$set 实例方法,这是全局 Vue.set 方法的别名:
this.$set(this.someObject,'b',2)
Vue 不能检测以下数组的变动:
举个栗子:
var vm = new Vue({
data: {
array: ['a', 'b', 'c']
}
});
vm.array[1] = 'x' //不是响应性的
vm.array.length = 2 //不是响应性的
为了解决第一类问题,以下三种方式都可以实现和 vm.array[index] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:
// Vue.set
Vue.set(vm.array, index, newValue)
// Array.prototype.splice
vm.array.splice(index, 1, newValue)
//vm.$set
vm.$set(vm.array, index, newValue)
为了解决第二类问题,你可以使用 splice:
vm.array.splice(newLength)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/180726.html原文链接:https://javaforall.cn