阅读 36

面试问:如何在IE8以下实现数据的双向绑定

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,同样可以实现数据的双向绑定。

由于我自己能力有限,在这里就实现这么多了,如果各位有兴趣的话,可以自己实现一下。

关注下面的标签,发现更多相似文章
评论