用原生Javascript对象中的访问器属性实现双向数据绑定

摘要:本文主要主要分文两个部分,第一个部分介绍javascript对象的两种属性,及数据属性和访问器属性。第二个部分详细讲解如何利用访问器属性实现简单的双向数据绑定。

一、javascript对象属性

1.1什么是javascript对象

ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数“。我们可以简单把javascript理解为一组无序的名值对集合,这组名值对中的值可以包括简单数据类型的值(字符串、布尔值等)也可以是应用数据类型的值(对象或函数)。

创建对象也主要有两种方法:第一种方法通过Object()构造函数:

var person = new Object();
person.name = 'jocs';
person.sayName = function(){
    console.log(this.name);
};
第二种方法是通过对象字面量语法来申明对象:

var person = {
    name: 'jocs',
    sayName: function(){
        console.log(this.name);
    }
};

1.2 Javascript对象的属性

ECMAScript中定义对象有两种属性:数据属性和访问器属性。

1.2.1 数据属性

数据属性包含了数据值的位置,在这个位置可以读取和写入数据值,数据属性拥有四个描述其行为的特性:

1、[[Configurable]]表示能否通过delete删除属性,能否修改属性的特性,或者能够把属性修改为访问器属性。取值可以为true和false。默认值为true。

2、[[Enumerable]]表示能够通过for-in循环来返回属性。默认值为true。

3、[[Writable]]表示能够修改属性的值,默认值为ture。

4、[[Value]]包含这个属性的数据值。默认值为undefined。

要修改属性默认的特性可以通过Object.defineProperty()方法。这个方法接受三个参数,属性所在的对象,属性的名字和一个描述符对象。例如:

<span style="font-size:14px;">var person = {};
Object.defineProperty(person, 'name', {
    writable: false,
    value: 'Jocs'
});

alert(person.name); // 'Jocs'
person.name = 'ransixi';
alert(person.name); //'Jocs'</span>

特别注意的是,在调用Object.defineProperty()方法的时候,如果不指定,configurable,writable,enumerable的话,特性的默认值都是false。

1.2.2 访问器属性

访问器属性不包括数据值,但是它包括一对函数,分别为:getter和setter函数。在读取访问器属性的时候会调用getter函数,在写入访问器属性的时候会调用setter函数。

访问器属性也拥有四个特性:

1.[[Configurable]]表示能够通过delete删除访问器属性,能够修改属性的特性,或者把属性转为数据属性。

2.[[Enumerable]]表示能够通过for-in循环来返回属性。

3.[[Get]] 在读取访问器属性时调用的函数。默认值为undefined。

4.[[Set]] 在写入访问器属性调用的函数。默认值为undefined。

访问器属性不能够直接在对象上定义,只能够通过Object.defineProperty()方法来定义。

<span style="font-size:14px;">var  person = {
    _name : 'jocs'
};
Object.defineProperty(person, 'name', {
    get: function(){
        return  this._name;
    },
    set: function(newValue){
       this._name = newValue;
    },
    configurable: true
});

console.log(person.name); // 'jocs'
person.name = 'ransixi';
console.log(person.name); // 'ransixi'</span>

二、通过访问器属性实现双向数据绑定

     

  //<input type = 'text' id = 'text1'/>
  var user ={},input = document.getElementById('text1');
  Object.defineProperty(user,'name',{
<span style="white-space:pre">	</span>get: function(){
<span style="white-space:pre">	</span>    return input.value;
<span style="white-space:pre">	</span>},
<span style="white-space:pre">	</span>set: function( newValue ){
<span style="white-space:pre">	</span>    input.value = newValue;
<span style="white-space:pre">	</span>},
<span style="white-space:pre">	</span>configurable: true
  });
<span style="white-space:pre">	</span>input.onchange = function(){
 <span style="white-space:pre">	</span>    user['name'] = user['name'];
      };

通过上面的javascript代码,我们实现了一个input输入框中的值和user中的访问器属性‘name’之间的双向数据绑定。我们在input元素上注册了一个onchange事件,当input输入框中的值发生变化并失去焦点时,会调用事件监听器上的处理函数。处理函数中就一行代码:user['name'] = user['name'];这一行代码其实做了两件事,第一件事是读取user中的访问器属性“name”,也就相应的调用了getter函数。第二件事是把读取的getter函数的返回值(这里是input.value)赋值给了user["name"]。也就相应的调用了setter函数。因此当输入框中数据发生变化时,user访问器属性getter函数返回值也发生了变化。换句话说就是当访问访问器属性的时候所得值也发生了变化。这也就完成了从输入框当user.name的数据绑定。

当我们通过user的访问器属性的setter方法传入newValue时候,input.value的值也被赋值成了newValue.也就就完成了从user的访问器属性到输入框input的数据绑定。从而实现了双向数据绑定。

但是当有两个输入框中的值想同时绑定user.name的时候怎么办呢?


var user = {}, 
   input1 = document.getElementById('text1'), 
   input2 = document.getElementById('text2');


function twoWayBind(obj, property, ele1, ele2){
    Object.defineProperty(obj, property, {
        get: function(){
            return ele1.value;
        },
        set: function(newValue){
            ele2.value = newValue; 
        },
        configurable: true
    });
ele1.onchange = function(){
    obj[property] = obj[property];
};
ele2.onchange = function(){
    ele1.value = this.value;
};
}
twoWayBind(user, 'name', input1, input2);

实现原理和一个输入框差不多,都是通过对象的访问器属性上面的getter和setter方法。唯一区别是,我们在input2输入框上面注册了一个事件,当input2输入框中内容发生变化时,input1中输入框的内容被赋值为input2输入框中的内容。当user.name调用setter函数的时候,input2输入框的内容被赋值成为了newValue。这样就完成了两个输入框和user的访问器属性‘name’之间的双向数据绑定。



猜你喜欢

转载自blog.csdn.net/magiclr/article/details/47905997