Object.defineProperty
我们都知道Vue是使用Object.defineProperty
来实现的数据双向绑定。我们先来实现一下数据的双向绑定。
var obj = {};
var a;
Object.defineProperty(obj,'a',{
get: function(){
console.log('get val');
return a;
},
set: function(newVal){
console.log('set val : ' + newVal);
a = newVal;
}
})
复制代码
这样就可以实现一个数据的双向绑定。如果加上input只要稍微改造一下就可以
。
<input type="text" id="input">
复制代码
js部分
var input = document.querySelector("#input");
var obj = {};
var a;
Object.defineProperty(obj, 'a', {
get: function () {
return a;
},
set: function (newVal) {
input.value = newVal;
a = newVal;
}
})
input.addEventListener('input', function (e) {
obj.a = e.target.value;
console.log(obj.a);
})
复制代码
这样就实现了一个双向数据绑定,但是
Object.defineProperty
并不是完美的,它有优点也有缺点。
- 优点:对一个对象可以做到完整的监听。
- 缺点:
Object.defineProperty
是ES5的API,向下兼容性很不好。
面试有时候也经常会问到:怎么样实现IE8及一下的双向数据绑定。
对于上面这个问题,我们可以使用API的私有属性。
defineGetter__和__defineSetter
我们经常见到的__proto__
凡是以__
开头结尾的是浏览器的私有属性,__defineGetter__和__defineSetter__
同样也是私有属性,这两个属性和Object.defineProperty
一样都是对对象添加属性,Object.defineProperty
相当于这两个方法的合并。
怎么使用它呢?
这两个方法接收两个参数:
- 第一个参数是定义属性的名字。
- 第二个参数是一个函数。
例如:给obj对象添加一个name属性
obj.__defineSetter__('name',function(val){
console.log('set name :' + val);
})
obj.__defineGetter__('name',function(){
console.log('get name');
})
复制代码
如何使用这个API实现数据的双向绑定呢?我们来实现一下。
var input = document.querySelector("#input");
var obj = {};
input.addEventListener('input', function (e) {
obj.name = e.target.value;
console.log(obj.name);
})
var name;
obj.__defineSetter__('name',function(val){
input.value = val;
name = val;
})
obj.__defineGetter__('name',function(){
return name;
})
复制代码
哎呦,不错哦。
其他方式
在Vue未出现之前,也是有MVVM框架产生的,比如说San.js
,它也是传统的MVVM数据双向绑定并且兼容IE6。还有VBScript
,在VBScript中可以写类,类中可以定义getter和setter,同样可以实现数据的双向绑定。
由于我自己能力有限,在这里就实现这么多了,如果各位有兴趣的话,可以自己实现一下。