前言
随着vue的使用逐渐深入,偶尔会在项目中发现明明按照文档上面去做了,但是并没有实际效果的情况。或者在使用一些功能的时候发现官方文档上面提供的方法不足以解决问题,之后还得百度或者查api,于是乎我决定慢慢开始由浅入深的了解vue的内部原理,知其然,还得知其所以然,否则每次都是治标不治本。
最近参与了一个jQuery项目之后才蓦然发现vue的方便,那么,都说vue是一个响应式mvvm框架,习惯于data进行双向数据绑定之后并没有觉得有什么不妥,可是,更深入的时候才发现我的认知里还是一片空白的。翻阅官方文档的描述,发现vue原来是通过Object.defineProperty
来追踪变化的。于是就以这篇文章就来记录一下我对Object.defineProperty
的理解好了。
Object.defineProperty有什么用
MDN上面的定义是这样的: Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
-
参数
Object.defineProperty(obj, prop, descriptor)
有三个参数,
obj
:表示需要定义属性的对象
prop
:表示需要在这个对象上定义或者修改的属性名(只是属性名而不是键值对)
descriptor
:文档中称其为属性描述符,这个属性描述符其实是一个对象,里面有若干属性,其中就有给上面对象obj
的属性prop
赋值用的属性value
,后文再详细叙说。 -
vue中的
Object.definePropert
而它和vue有什么关系呢,当我们改变了data中的属性值,其实相当于调用了Object.defineProperty
方法,obj
可以看作是整个data,而我们改变的某个属性就是prop
了,我们在外部直接改变prop的之后(它的值也可以通过descriptor
中的value
改写),然后通过descriptor
中的存取描述符相关操作再改变dom中的值。寥寥几笔虽然勉强概括了vue的工作过程,但其实vue对这一过程还经过了多层封装处理进行优化,这其中我也只是一知半解还有待细细研究。本文接下来就重点来解释descriptor
这个参数。
属性描述符 descriptor
属性描述符——这个描述符里面一些属性,就如同字面上的意思一样,这些属性是用来描述和改写外面的属性prop
的。属性描述符有两种形式:数据描述符和存取描述符,属性描述符必须是这两者其中一种,不能同时是这两者。本文只重点介绍存取描述符。
-
存取描述符的一些属性
configurable
表示该属性能否被改变或者删除,默认为false。
enumerable
表示该属性是否可以被枚举(遍历),默认为false。
get
一个给属性提供 getter 的方法,当读取该属性的时候会调用这个方法。
set
一个给属性提供 setter 的方法,当该属性发生变化的时候会调用这个方法。
其实前两个是数据描述符和存取描述符共有的方法,get-set才是属性描述符特有的方法,而前文提到的value
则是数据描述符特有的方法,可以用来改变prop
的值,当然我们一般都会使用点语法直接给一个对象的属性赋值。
- get与set
get与set,第一眼看上去是否有种似曾相识的感觉,没错vue中的计算属性也用了这个语法糖,一样的意思,只不过computed
中一般只用到了get,于是都省略了。
接下来简单的试一下
let data = {};
let domVal;
console.log(domVal);// 1
Object.defineProperty(data, "test", {
enumerable: true,
configurable: true,
get: function () {
return domVal;
},
set: function (newValue) {
domVal = newValue;
}
});
data.test = 5;
console.log(domVal);// 5
domVal
可以看作是在dom中绑定的值,当我们改变data中的test
的值的时候domVal
也会发生变化。当然这只是一个小小的演示,而vue中则要经过一个复杂的过程,最后才会编译到视图中去。所以以后有空我还会继续研究其中的奥秘。
最后,点击Object.defineProperty() | MDN,可以详细了解该方法的所有参数与属性。
网友评论