起因
当我打印出Vue实例下的data对象里的属性时,发现了一个有趣的事情:
它的每个属性都有两个相对应的get
和set
方法,我觉的这是多此一举的,于是去网上查了查Vue双向绑定的实现原理,才发现它和Angular.js双向绑定的实现原理完全不同,Angular是用的数据脏检测,当Model发生变化,会检测所有视图是否绑定了相关数据,再更改视图。而Vue使用的发布订阅模式,是点对点的绑定数据。
Vue的数据绑定只有两个步骤,compile=>link
。
我一直在想,vue是通过什么去监听用户对Model的修改,直到我发现Vue的data里,每个属性都有set
和get
属性,我才明白过来。
没有任何问题,但是如果要你去监测,当我修改了这个对象的属性时,要去做一些事,你会怎么做?
相关思考
这就要用到getter
和setter
了。
假设我现在要给一个编程之家对象添加一个name
属性,而且每次更新name
属性时,我要去完成一些事,我们可以这样做:
输出:
你会发现这个对象和最上面的Vue中的data
对象,打印出来的效果是一样的,都拥有get
和set
属性。
我们来一步步分析下上面的代码,很有趣。
我们先创建一个对象字面量:
再把this
缓存一下:
接下来是最重要的,我们return
了一个对象回去:
}
顾名思义,get为取值,set为赋值,正常情况下,我们取值和赋值是用obj.prop
的方式,但是这样做有一个问题,我如何知道对象的值改变了?所以就轮到set登场了。
你可以把get
和set
理解为function
,当然,只是可以这么理解,这是完全不一样的两个东西。
接下来创建一个编程之家的实例,isMe;此时,isMe是没有name
属性的,当我们调用isMe.name
时,我们会进入到get name(){...}
中,先判断isMe是否有name
属性,答案是否定的,那麽就添加一个name
属性,并给它赋值:"你还没有取名";如果有name
属性,那就返回name
属性。
看到这里你一定知道get
怎么使用了,对,你可以把get
看成一个取值的函数,函数的返回值就是它拿到的值。
我感觉比较重要的是set
属性,当我给实例赋值:
此时,会进入set name(val){...};
形参val就是我赋给name
属性的值,在这个函数里,我就可以做很多事了,比如双向绑定!因为这个值的每次改变都必须经过set,其他方式是改变不了它的,相当于一个万能的监听器。
ES5的对象原型有两个新的属性__defineGetter__
和__defineSetter__
,专门用来给对象绑定get和set。
可以这样书写:
效果是一样的,建议使用下面这种方式,因为是在原型上书写,所以可以继承和重用。