1. 程式人生 > >從Object.definedProperty中看vue的雙向資料的繫結

從Object.definedProperty中看vue的雙向資料的繫結

前言

Object.defineProperty是ES5中的方法,它可以直接在一個物件上定義一個新屬性,或者修改一個物件的現有屬性, 並返回這個物件。vue.js正式利用這種方法實現資料的雙向繫結,以達到響應式的目的。

1、語法

Object.defineProperty(object, propertyname, descriptor)  //引數(3個且必須)

2、引數詳解

  3.1、object:要在其上新增或修改屬性的物件。   3.2、propertyname:一個包含屬性名稱的字串。就是需要定義的屬性和方法。   3.3、descriptor:可以包含以下屬性,預設情況下, writable, enumerable,configurable值為false

  value:屬性的值

  writable:如果為false,屬性的值就不能被重寫,只能為只讀了。

  enumerable:是否能列舉,也就是否能在for...in迴圈中遍歷出來或在Object.keys中列舉出來。

  configurable:如果為false,就不能再設定他的(value,writable,configurable)。

還有兩個方法 (雙向資料繫結正是利用了這兩個方法,即訪問器 )get() 和 set()

3、看看栗子

1

2

3

4

5

var a= {}

Object.defineProperty(a,

"b",{

value:111

})

console.log(a.b);//111

就是給a物件新增b屬性,並返回a物件;

再比如:把描述設定為不可寫; 

4、訪問器 set和get

set();一旦屬性被重新賦值,此方法被自動呼叫。 get();一旦屬性被訪問讀取,此方法被自動呼叫。 不能同時設定訪問器 (get 和 set) 和 wriable 或 value,否則會錯。

1

2

3

4

5

6

7

8

9

10

11

12

var

 a= {}

Object.defineProperty(a,"b",{

set:function(val){

console.log("賦值時候呼叫我,我的新值是"+ val)

},

get:function(){

console.log("取值的時候呼叫我")

return 123

}

})

a.b =520          // 賦值時候呼叫我,我的新值是520

console.log(a.b)  // 取值的時候呼叫我, 返回我設定123,不是開始設定的520 

5、簡單雙向資料繫結

給物件a定義新的屬性b,並且定義屬性b的get和set方法,當a.b的時候會呼叫b屬性的get方法,給b屬性賦值的時候,會呼叫set方法,這就是修改資料的時候,檢視會自動更新的關鍵.(只能相容IE8以上的瀏覽器,vue也是如此!)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<label>輸入:</label><input type="text" id="demo1"><br/>

<label>輸出:</label> <input type="textarea" id="demo2"></input>

<script>

var a={};

var output=[];

Object.defineProperty(a,'b',{   //給a物件新增b屬性

set:function(val){

output['b']=val;

},

get:function(){

return output['b'];

}

})

var demo1=document.querySelector('#demo1');

var demo2=document.querySelector('#demo2');

demo1.onkeyup=function(){

a.b=demo1.value;//給a物件新增b屬性時候,觸發了a的set方法,此時#demo1的value值賦值給output['b']。

demo2.value=output['b'];

}

</script>

6、再看看Object.defineProperty實踐例子

直接在原型上新增一個不可遍歷的方法extend(),該方法可以把新物件賦值給舊物件;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

Object.defineProperty(Object.prototype, 'extend',{

value : function(def, opt) {

for(var key in opt){

def[key] = opt[key];

}

return def;

},

writable: true,

enumerable : false

});

function func(options){

let def = {

payType: 'wechat',

buyType: -1,

isCard: false,

toUid: -1,

couponId: -1

};

let opt = extend(def, options);

this.isCardPay = opt.isCard;

this.payType = opt.payType;

.......

}

//使用

fuc({

payType: 'ali',

buyType: 2,

isCard: true,

toUid: 123456,

couponId: 667890

})

 7、vue怎麼實現資料雙向繫結?

vue.js 則是採用資料劫持結合釋出者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的settergetter,在資料變動時釋出訊息給訂閱者,觸發相應的監聽回撥。