公司的新项目决定使用Vue.js来做,当我打印出Vue实例下的data对象里的属性时,发现了一个有趣的事情:

它的每个属性都有两个相对应的get和set方法,我觉的这是多此一举的,于是去网上查了查Vue双向绑定的实现原理,才发现它和Angular.js双向绑定的实现原理完全不同,Angular是用的数据脏检测,当Model发生变化,会检测所有视图是否绑定了相关数据,再更改视图。而Vue使用的发布订阅模式,是点对点的绑定数据。

Vue的数据绑定只有两个步骤,compile=>link。

我一直在想,vue是通过什么去监听用户对Model的修改,直到我发现Vue的data里,每个属性都有set和get属性,我才明白过来。

在平时,我们创建一个对象,并修改它的属性,是这样的:

    var obj = {
val:99
}
obj.val = 100;
console.log(obj.val)//

没有任何问题,但是如果要你去监测,当我修改了这个对象的属性时,要去做一些事,你会怎么做?

这就要用到getter和setter了。

假设我现在要给一个码农对象添加一个name属性,而且每次更新name属性时,我要去完成一些事,我们可以这样做:

    var Coder = function() {
var that = this;
return {
get name(){
if(that.name){
return that.name
}
return '你还没有取名'
},
set name(val){
console.log('你把名字修成了'+val)
that.name = val
}
}
}
var isMe = new Coder()
console.log(isMe.name)
isMe.name = '周神'
console.log(isMe.name)
console.log(isMe)

输出:

你会发现这个对象和最上面的Vue中的data对象,打印出来的效果是一样的,都拥有get和set属性。

我们来一步步分析下上面的代码,很有趣。

我们先创建一个对象字面量:

var Coder = function() {...}

再把this缓存一下:

var that = this;

接下来是最重要的,我们return了一个对象回去:

{

  get name(){...},

  set name(val){...}

}

顾名思义,get为取值,set为赋值,正常情况下,我们取值和赋值是用obj.prop的方式,但是这样做有一个问题,我如何知道对象的值改变了?所以就轮到set登场了。

你可以把get和set理解为function,当然,只是可以这么理解,这是完全不一样的两个东西。

接下来创建一个码农的实例,isMe;此时,isMe是没有name属性的,当我们调用isMe.name时,我们会进入到get name(){...}中,先判断isMe是否有name属性,答案是否定的,那麽就添加一个name属性,并给它赋值:"你还没有取名";如果有name属性,那就返回name属性。

看到这里你一定知道get怎么使用了,对,你可以把get看成一个取值的函数,函数的返回值就是它拿到的值。

我感觉比较重要的是set属性,当我给实例赋值:

isMe.name="周神"

此时,会进入set name(val){...};形参val就是我赋给name属性的值,在这个函数里,我就可以做很多事了,比如双向绑定!因为这个值的每次改变都必须经过set,其他方式是改变不了它的,相当于一个万能的监听器。

还有另一种方法可以实现这个功能。

ES5的对象原型有两个新的属性__defineGetter__和__defineSetter__,专门用来给对象绑定get和set。可以这样书写:

    var Coder = function() {
}
Coder.prototype.__defineGetter__('name', function() {
if (this.name) {
return this.name
}else{
return '你还没有取名'
}
})
Coder.prototype.__defineSetter__('name', function(val) {
this.name = val
})
var isMe = new Coder()
console.log(isMe.name)
isMe.name = '周神'
console.log(isMe.name)
console.log(isMe)

效果是一样的,建议使用下面这种方式,因为是在原型上书写,所以可以继承和重用,最近想写点小框架,才发现知识不够用,大家一起加油吧!

最新文章

  1. HDU 3089 (快速约瑟夫环)
  2. C++ 类里面,函数占用存储空间问题
  3. mysql查询所有表行数
  4. amcharts简单封装
  5. SimpleTagImageView
  6. MVC-Razor引擎布局
  7. 高效实现 std::string split() API
  8. python-线程、进程、协程
  9. 动态面板——axure线框图部件库介绍
  10. 使用zTree和json构建简单树节点
  11. mysql中You can't specify target table for update in FROM clause
  12. java启动子进程以及进程通信
  13. Android Weekly Notes Issue #249
  14. vue移动端常用组件
  15. 如何发起、防御和测试XSS攻击,我们用DVWA来学习(下)
  16. Python 之 type方法创建类
  17. python API whoami
  18. laravel 制作购物车流程
  19. Linux中查找当前目录下占用空间最大的前10个文件
  20. Estimation And Gain

热门文章

  1. Cocos2d-x 3.2 学习笔记(十四)保卫萝卜之界面UI
  2. 使用Nginx配置NodeJs程序(Windows平台)
  3. Android基于mAppWidget实现手绘地图(四)--如何附加javadoc
  4. 理解SQL Server是如何执行查询的 (2/3)
  5. 解决MVC EF Code First错误:Model compatibility cannot be checked because the EdmMetadata type was not included in the model.
  6. 相关子查询【SQL Server】
  7. 数据结构 - Codeforces Round #353 (Div. 2) D. Tree Construction
  8. 从C#到Objective-C,循序渐进学习苹果开发(1)--准备开发账号和开发环境
  9. iOS阶段学习第14天笔记(NSString与NSMutableString)
  10. Ext.grid.Panel表格分页存储过程