Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
´ÓJavaScriptÊôÐÔÃèÊöÆ÷ÆÊÎöVue.jsÏìӦʽÊÓͼ
 
À´Ô´£º²©¿Í ·¢²¼ÓÚ£º2017-7-21
  1977  次浏览      27
 

ǰÑÔ

JavaScriptµÄ¶ÔÏó£¬ÊÇÒ»×é¼üÖµ¶ÔµÄ¼¯ºÏ£¬¿ÉÒÔÓµÓÐÈÎÒâÊýÁ¿µÄΨһ¼ü£¬¼ü¿ÉÒÔÊÇ×Ö·û´®£¨String£©ÀàÐÍ»ò±ê¼Ç£¨Symbol£¬ES6ÐÂÔöµÄ»ù±¾Êý¾ÝÀàÐÍ£©ÀàÐÍ£¬Ã¿¸ö¼ü¶ÔÓ¦Ò»¸öÖµ£¬Öµ¿ÉÒÔÊÇÈÎÒâÀàÐ͵ÄÈÎÒâÖµ¡£¶ÔÓÚ¶ÔÏóÄÚµÄÊôÐÔ£¬JavaScriptÌṩÁËÒ»¸öÊôÐÔÃèÊöÆ÷½Ó¿ÚPropertyDescriptor£¬´ó²¿·Ö¿ª·¢Õß²¢²»ÐèÒªÖ±½ÓʹÓÃËü£¬µ«ÊǺܶà¿ò¼ÜºÍÀà¿âÄÚ²¿ÊµÏÖʹÓÃÁËËü£¬Èçavalon.js£¬Vue.js£¬±¾Æª½éÉÜÊôÐÔÃèÊöÆ÷¼°Ïà¹ØÓ¦Óá£

¶¨Òå¶ÔÏóÊôÐÔ

ÔÚ½éÉܶÔÏóÊôÐÔÃèÊö֮ǰ£¬ÏȽéÉÜÒ»ÏÂÈçºÎ¶¨Òå¶ÔÏóÊôÐÔ¡£×î³£Óõķ½Ê½¾ÍÊÇʹÓÃÈçÏ·½Ê½£º


var a = {
name: 'jh'
};

// or
var b = {};
b.name = 'jh';

// or
var c = {};
var key = 'name';
c[key] = 'jh';

±¾ÎÄʹÓÃ×ÖÃæÁ¿·½Ê½´´½¨¶ÔÏ󣬵«ÊÇJavaScript»¹ÌṩÆäËû·½Ê½£¬È磬new Object()£¬Object.create()£¬Á˽â¸ü¶àÇë²é¿´¶ÔÏó³õʼ»¯¡£

Object.defineProperty()

ÉÏÃæÍ¨³£Ê¹Óõķ½Ê½²»ÄÜʵÏÖ¶ÔÊôÐÔÃèÊöÆ÷µÄ²Ù×÷£¬ÎÒÃÇÐèҪʹÓÃdefineProperty()·½·¨£¬¸Ã·½·¨ÎªÒ»¸ö¶ÔÏó¶¨ÒåÐÂÊôÐÔ»òÐÞ¸ÄÒ»¸öÒѶ¨ÒåÊôÐÔ£¬½ÓÊÜÈý¸ö²ÎÊýObject.defineProperty(obj, prop, descriptor)£¬·µ»ØÖµÎª²Ù×÷ºóµÄ¶ÔÏó£º

1.obj, ´ý²Ù×÷¶ÔÏó

2.ÊôÐÔÃû

3.²Ù×÷ÊôÐÔµÄÊôÐÔÃèÊö¶ÔÏó

var x = {};
Object.defineProperty(x, 'count', {});
console.log(x); // Object {count: undefined}

ÓÉÓÚ´«ÈëÒ»¸ö¿ÕµÄÊôÐÔÃèÊö¶ÔÏó£¬ËùÒÔÊä³ö¶ÔÏóÊôÐÔֵΪundefined£¬µ±Ê¹ÓÃdefineProperty()·½·¨²Ù×÷ÊôÐÔʱ£¬ÃèÊö¶ÔÏóĬÈÏֵΪ£º

1.value: undefined

2.set: undefined

3.get: undefined

4.writable: false

5.enumerable: false,

6.configurable: false

²»Ê¹Óø÷½·¨¶¨ÒåÊôÐÔ£¬ÔòÊôÐÔĬÈÏÃèÊöΪ£º

1.value: undefined

2.set: undefined

3.get: undefined

4.writable: true

5.enumerable: true,

6.configurable: true

ĬÈÏÖµ¾ù¿É±»Ã÷È·²ÎÊýÖµÉèÖø²¸Ç¡£

µ±È»»¹Ö§³ÖÅúÁ¿¶¨Òå¶ÔÏóÊôÐÔ¼°ÃèÊö¶ÔÏó£¬Ê¹Óá°Object.defineProperties()`·½·¨£¬È磺

var x = {};
Object.defineProperties(x, {
count: {
value: 0
},
name: {
value: 'jh'
}
});
console.log(x); // Object {count: 0, name: 'jh'}

¶ÁÈ¡ÊôÐÔÃèÊö¶ÔÏó

JavaScriptÖ§³ÖÎÒÃǶÁȡij¶ÔÏóÊôÐÔµÄÃèÊö¶ÔÏó£¬Ê¹Óà Object . getOwnPropertyDescriptor ( obj , prop )·½·¨

var x = {
name: 'jh'
};
Object.defineProperty(x, 'count', {});
Object.getOwnPropertyDescriptor(x, 'count');
Object.getOwnPropertyDescriptor(x, 'name');

// Object {value: undefined, writable:

false, enumerable: false, configurable: false}
// Object {value: "jh", writable: true,

enumerable: true, configurable: true}

¸ÃʵÀýÒ²Ó¡Ö¤ÁËÉÏÃæ½éÉܵÄÒÔ²»Í¬·½Ê½¶¨ÒåÊôÐÔʱ£¬ÆäĬÈÏÊôÐÔÃèÊö¶ÔÏóÊDz»Í¬µÄ¡£

ÊôÐÔÃèÊö¶ÔÏó

PropertyDescriptor APIÌṩÁËÁù´óʵÀýÊôÐÔÒÔÃèÊö¶ÔÏóÊôÐÔ£¬°üÀ¨£º configurable , enumerable , get , set , value , writable .

value

Ö¸¶¨¶ÔÏóÊôÐÔÖµ£º


var x = {};
Object.defineProperty(x, 'count', {
value: 0
});
console.log(x); // Object {count: 0}

writable

Ö¸¶¨¶ÔÏóÊôÐÔÊÇ·ñ¿É±ä£º


var x = {};
Object.defineProperty(x, 'count', {
value: 0
});
console.log(x); // Object {count: 0}
x.count = 1; // ¾²Ä¬Ê§°Ü£¬²»»á±¨´í
console.log(x); // Object {count: 0}

ʹÓÃdefineProperty()·½·¨Ê±£¬Ä¬ÈÏÓÐwritable: false£¬ ÐèÒªÏÔʾÉèÖÃwritable: true¡£

´æÈ¡Æ÷º¯Êý(getter/setter)

¶ÔÏóÊôÐÔ¿ÉÒÔÉèÖôæÈ¡Æ÷º¯Êý£¬Ê¹ÓÃgetÉùÃ÷´æÈ¡Æ÷getterº¯Êý£¬setÉùÃ÷´æÈ¡Æ÷setterº¯Êý£»Èô´æÔÚ´æÈ¡Æ÷º¯Êý£¬ÔòÔÚ·ÃÎÊ»òÉèÖøÃÊôÐÔʱ£¬½«µ÷ÓöÔÓ¦µÄ´æÈ¡Æ÷º¯Êý:

GET

¶ÁÈ¡¸ÃÊôÐÔֵʱµ÷Óøú¯Êý²¢½«¸Ãº¯Êý·µ»ØÖµ¸³Öµ¸øÊôÐÔÖµ£»


var x = {};
Object.defineProperty(x, 'count', {
get: function() {
console.log('¶ÁÈ¡countÊôÐÔ +1');
return 0;
}
});
console.log(x); // Object {count: 0}
x.count = 1;
// '¶ÁÈ¡countÊôÐÔ +1'
console.log(x.count); // 0

SET

µ±ÉèÖú¯Êýֵʱµ÷Óøú¯Êý£¬¸Ãº¯Êý½ÓÊÕÉèÖõÄÊôÐÔÖµ×÷²ÎÊý£º


var x = {};
Object.defineProperty(x, 'count', {
set: function(val) {
this.count = val;
}
});
console.log(x);
x.count = 1;

Ö´ÐÐÉÏËß´úÂ룬»á·¢ÏÖ±¨´í£¬Ö´ÐÐÕ»Òç³ö:

ÉÏÊö´úÂëÔÚÉèÖÃcountÊôÐÔʱ£¬»áµ÷ÓÃset·½·¨£¬¶øÔڸ÷½·¨ÄÚΪcountÊôÐÔ¸³Öµ»áÔٴδ¥·¢set·½·¨£¬ËùÒÔÕâÑùÊÇÐв»Í¨µÄ£¬JavaScriptʹÓÃÁíÒ»ÖÖ·½Ê½£¬Í¨³£´æÈ¡Æ÷º¯ÊýµÃͬʱÉùÃ÷£¬´úÂëÈçÏ£º


var x = {};
Object.defineProperty(x, 'count', {
get: function() {
return this._count;
},
set: function(val) {
console.log('ÉèÖÃcountÊôÐÔ +1');
this._count = val;
}
});
console.log(x); // Object {count: undefined}
x.count = 1;
// 'ÉèÖÃcountÊôÐÔ +1'
console.log(x.count); 1

ÊÂʵÉÏ£¬ÔÚʹÓÃdefineProperty()·½·¨ÉèÖÃÊôÐÔʱ£¬Í¨³£ÐèÒªÔÚ¶ÔÏóÄÚ²¿Î¬»¤Ò»¸öÐÂÄÚ²¿±äÁ¿£¨ÒÔÏ»®Ïß_¿ªÍ·£¬±íʾ²»Ï£Íû±»Íⲿ·ÃÎÊ£©£¬×÷Ϊ´æÈ¡Æ÷º¯ÊýµÄÖн顣

×¢£ºµ±ÉèÖÃÁË´æÈ¡Æ÷ÃèÊöʱ£¬²»ÄÜÉèÖÃvalueºÍwritableÃèÊö¡£

ÎÒÃÇ·¢ÏÖ£¬ÉèÖÃÊôÐÔ´æÈ¡Æ÷º¯Êýºó£¬ÎÒÃÇ¿ÉÒÔʵÏÖ¶Ô¸ÃÊôÐÔµÄʵʱ¼à¿Ø£¬ÕâÔÚʵ¼ùÖкÜÓÐÓÃÎäÖ®µØ£¬ºóÎÄ»áÓ¡Ö¤ÕâÒ»µã¡£

enumerable

Ö¸¶¨¶ÔÏóÄÚijÊôÐÔÊÇ·ñ¿Éö¾Ù£¬¼´Ê¹ÓÃfor in²Ù×÷ÊÇ·ñ¿É±éÀú£º


var x = {
name: 'jh'
};
Object.defineProperty(x, 'count', {
value: 0
});
for (var key in x) {
console.log(key + ' is ' + x[key]);
}
// name is jh

ÉÏÃæÎÞ·¨±éÀúcountÊôÐÔ£¬ÒòΪʹÓÃdefineProperty()·½·¨Ê±£¬Ä¬ÈÏÓÐenumerable: false£¬ÐèÒªÏÔʾÉùÃ÷¸ÃÃèÊö£º


var x = {
name: 'jh'
};
Object.defineProperty(x, 'count', {
value: 0,
enumerable: true
});
for (var key in x) {
console.log(key + ' is ' + x[key]);
}
// name is jh
// count is 0
x.propertyIsEnumerable('count'); // true

configurable

¸ÃÖµÖ¸¶¨¶ÔÏóÊôÐÔÃèÊöÊÇ·ñ¿É±ä£º


var x = {};
Object.defineProperty(x, 'count', {
value: 0,
writable: false
});
Object.defineProperty(x, 'count', {
value: 0,
writable: true
});

Ö´ÐÐÉÏÊö´úÂë»á±¨´í£¬ÒòΪʹÓÃdefineProperty()·½·¨Ê±Ä¬ÈÏÊÇ configurable : false £¬Êä³öÈçͼ£º

ÐÞ¸ÄÈçÏ£¬¼´¿É£º


var x = {};
Object.defineProperty(x, 'count', {
value: 0,
writable: false,
configurable: true
});
x.count = 1;
console.log(x.count); // 0
Object.defineProperty(x, 'count', {
writable: true
});
x.count = 1;
console.log(x.count); // 1

ÊôÐÔÃèÊöÓëÊÓͼģÐͰó¶¨

½éÉÜÍêÊôÐÔÃèÊö¶ÔÏó£¬ÎÒÃÇÀ´¿´¿´ÆäÔÚÏÖ´úJavaScript¿ò¼ÜºÍÀà¿âÉϵÄÓ¦Óá£Ä¿Ç°Óкܶà¿ò¼ÜºÍÀà¿âʵÏÖÊý¾ÝºÍDOMÊÓͼµÄµ¥ÏòÉõÖÁË«Ïò°ó¶¨£¬ÈçReact£¬angular.js£¬avalon.js,£¬Vue.jsµÈ£¬Ê¹ÓÃËüÃǺÜÈÝÒ××öµ½¶ÔÊý¾Ý±ä¸ü½øÐÐÏìӦʽ¸üÐÂDOMÊÓͼ£¬ÉõÖÁÊÓͼºÍÄ£ÐÍ¿ÉÒÔʵÏÖË«Ïò°ó¶¨£¬Í¬²½¸üС£µ±È»ÕâЩ¿ò¼Ü¡¢Àà¿âÄÚ²¿ÊµÏÖÔ­ÀíÖ÷Òª·ÖΪÈý´óÕóÓª¡£±¾ÎÄÒÔVue.jsΪÀý£¬Vue.jsÊǵ±Ï±ȽÏÁ÷ÐеÄÒ»¸öÏìӦʽµÄÊÓͼ²ãÀà¿â£¬ÆäÄÚ²¿ÊµÏÖÏìӦʽԭÀí¾ÍÊDZ¾ÎĽéÉܵÄÊôÐÔÃèÊöÔÚ¼¼ÊõÖеľßÌåÓ¦Óá£

¿ÉÒÔµã»÷´Ë´¦£¬²é¿´Ò»¸öÔ­ÉúJavaScriptʵÏֵļòÒ×Êý¾ÝÊÓͼµ¥Ïò°ó¶¨ÊµÀý£¬ÔÚ¸ÃʵÀýÖУ¬µã»÷°´Å¥¿ÉÒÔʵÏÖ¼ÆÊý×ÔÔö£¬ÔÚÊäÈë¿òÊäÈëÄÚÈÝ»áͬ²½¸üе½Õ¹Ê¾DOM£¬ÉõÖÁÔÚ¿ØÖÆÌ¨¸Ä±ädata¶ÔÏóÊôÐÔÖµ£¬DOM»áÏìÓ¦¸üУ¬Èçͼ£º

Êý¾ÝÊÓͼµ¥Ïò°ó¶¨

ÏÖÓÐÈçÏ´úÂ룺


var data = {};
var contentEl = document.querySelector('.content');


Object.defineProperty(data, 'text', {
writable: true,
configurable: true,
enumerable: true,
get: function() {
return contentEl.innerHTML;
},
set: function(val) {
contentEl.innerHTML = val;
}
});

ºÜÈÝÒ׿´³ö£¬µ±ÎÒÃÇÉèÖÃdata¶ÔÏóµÄtextÊôÐÔʱ£¬»á½«¸ÃÖµÉèÖÃΪÊÓͼDOMÔªËØµÄÄÚÈÝ£¬¶ø·ÃÎʸÃÊôÐÔֵʱ£¬·µ»ØµÄÊÇÊÓͼDOMÔªËØµÄÄÚÈÝ£¬Õâ¾Í¼òµ¥µÄʵÏÖÁËÊý¾Ýµ½ÊÓͼµÄµ¥Ïò°ó¶¨£¬¼´Êý¾Ý±ä¸ü£¬ÊÓͼҲ»á¸üС£

ÒÔÉϽöÊÇÕë¶ÔÒ»¸öÔªËØµÄÊý¾ÝÊÓͼ°ó¶¨£¬µ«ÉÔ΢Óо­ÑéµÄ¿ª·¢Õß±ã¿ÉÒÔ¸ù¾ÝÒÔÉÏ˼·£¬½øÐзâ×°£¬ºÜÈÝÒ×µÄʵÏÖÒ»¸ö¼òÒ×µÄÊý¾Ýµ½ÊÓͼµ¥Ïò°ó¶¨µÄ¹¤¾ßÀà¡£

³éÏó·â×°

½ÓÏÂÀ´¶ÔÒÔÉÏʵÀý½øÐмòµ¥³éÏó·â×°£¬µã»÷²é¿´ÍêÕûʵÀý´úÂë¡£

Ê×ÏÈÉùÃ÷Êý¾Ý½á¹¹£º


window.data = {
title: 'Êý¾ÝÊÓͼµ¥Ïò°ó¶¨',
content: 'ʹÓÃÊôÐÔÃèÊöÆ÷ʵÏÖÊý¾ÝÊÓͼ°ó¶¨',
count: 0
};
var attr = 'data-on'; // Ô¼¶¨ºÃµÄÓï·¨£¬

ÉùÃ÷DOM°ó¶¨¶ÔÏóÊôÐÔ

È»ºó·â×°º¯ÊýÅúÁ¿´¦Àí¶ÔÏ󣬱éÀú¶ÔÏóÊôÐÔ£¬ÉèÖÃÃèÊö¶ÔÏóͬʱΪÊôÐÔ×¢²á±ä¸üʱµÄ»Øµ÷£º

// Ϊ¶ÔÏóÖÐÿһ¸öÊôÐÔÉèÖÃÃèÊö¶ÔÏó£¬ÓÈÆäÊÇ´æÈ¡Æ÷º¯Êý
function defineDescriptors(obj) {
for (var key in obj) {
// ±éÀúÊôÐÔ
defineDescriptor(obj, key, obj[key]);
}

// ÎªÌØ¶¨ÊôÐÔÉèÖÃÃèÊö¶ÔÏó
function defineDescriptor(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function() {
var value = val;
return value;
},
set: function(newVal) {
if (newVal !== val) {
// Öµ·¢Éú±ä¸ü²ÅÖ´ÐÐ
val = newVal;
Observer.emit(key, newVal); // ´¥·¢¸üÐÂDOM
}
}
});
Observer.subscribe(key); // Ϊ¸ÃÊôÐÔ×¢²á»Øµ÷
}
}

¹ÜÀíʼþ

ÒÔ·¢²¼¶©ÔÄģʽ¹ÜÀíÊôÐÔ±ä¸üʼþ¼°»Øµ÷£º

// ʹÓ÷¢²¼/¶©ÔÄģʽ£¬¼¯ÖйÜÀí¼à¿ØºÍ´¥·¢»Øµ÷ʼþ
var Observer = {
watchers: {},
subscribe: function(key) {
var el = document.querySelector('[' +

attr + '="'+ key + '"]');

// demo
var cb = function react(val) {
el.innerHTML = val;
}

if (this.watchers[key]) {
this.watchers[key].push(cb);
} else {
this.watchers[key] = [].concat(cb);
}
},
emit: function(key, val) {
var len = this.watchers[key] && this.

watchers[key].length;

if (len && len > 0) {
for(var i = 0; i < len; i++) {
this.watchers[key][i](val);
}
}
}
};

³õʼ»¯ÊµÀý

×îºó³õʼ»¯ÊµÀý£º

// ³õʼ»¯demo
function init() {
defineDescriptors(data); // ´¦ÀíÊý¾Ý¶ÔÏó
var eles = document.querySelectorAll('[' + attr + ']');

// ³õʼ±éÀúDOMչʾÊý¾Ý
// Æäʵ¿ÉÒÔ½«¸Ã²Ù×÷·Åµ½ÊôÐÔÃèÊö¶ÔÏóµÄget·½·¨ÄÚ

£¬ÔòÔÚ³õʼ»¯Ê±Ö»ÐèÒª¶ÔÊôÐÔ±éÀú·ÃÎʼ´¿É
for (var i = 0, len = eles.length; i < len; i++) {
eles[i].innerHTML = data[eles[i].getAttribute(attr)];
}

// ¸¨Öú²âÊÔʵÀý
document.querySelector('.add').addEventListener

('click', function(e) {
data.count += 1;
});

}
init();

html´úÂë²Î¿¼ÈçÏ£º


<h2 class="title" data-on="title"></h2>
<div class="content" data-on="content"></div>
<div class="count" data-on="count"></div>
<div>
ÇëÊäÈëÄÚÈÝ£º
<input type="text" class="content-input"

placeholder="ÇëÊäÈëÄÚÈÝ">
</div>
<button class="add" onclick="">¼Ó1</button>

Vue.jsµÄÏìӦʽԭÀí

ÉÏÒ»½ÚʵÏÖÁËÒ»¸ö¼òµ¥µÄÊý¾ÝÊÓͼµ¥Ïò°ó¶¨ÊµÀý£¬ÏÖÔÚ¶ÔVue.jsµÄÏìӦʽµ¥Ïò°ó¶¨½øÐмòÒª·ÖÎö£¬Ö÷ÒªÐèÒªÀí½âÆäÈçºÎ×·×ÙÊý¾Ý±ä¸ü¡£

ÒÀÀµ×·×Ù

Vue.jsÖ§³ÖÎÒÃÇͨ¹ýdata²ÎÊý´«µÝÒ»¸öJavaScript¶ÔÏó×öΪ×é¼þÊý¾Ý£¬È»ºóVue.js½«±éÀú´Ë¶ÔÏóÊôÐÔ£¬Ê¹ÓÃObject.defineProperty·½·¨ÉèÖÃÃèÊö¶ÔÏó£¬Í¨¹ý´æÈ¡Æ÷º¯Êý¿ÉÒÔ×·×Ù¸ÃÊôÐԵıä¸ü£¬±¾ÖÊÔ­ÀíºÍÉÏÒ»½ÚʵÀý²î²»¶à£¬µ«ÊDz»Í¬µÄÊÇ£¬Vue.js´´½¨ÁËÒ»²ãWatcher²ã£¬ÔÚ×é¼þäÖȾµÄ¹ý³ÌÖаÑÊôÐԼǼΪÒÀÀµ£¬Ö®ºóµ±ÒÀÀµÏîµÄsetter±»µ÷ÓÃʱ£¬»á֪ͨWatcherÖØÐ¼ÆË㣬´Ó¶øÊ¹Ëü¹ØÁªµÄ×é¼þµÃÒÔ¸üÐÂ,ÈçÏÂͼ£º

Vue.jsÏìӦʽԭÀíͼ

×é¼þ¹ÒÔØÊ±£¬ÊµÀý»¯watcherʵÀý£¬²¢°Ñ¸ÃʵÀý´«µÝ¸øÒÀÀµ¹ÜÀíÀ࣬×é¼þäÖȾʱ£¬Ê¹ÓöÔÏó¹Û²ì½Ó¿Ú±éÀú´«ÈëµÄdata¶ÔÏó£¬ÎªÃ¿¸öÊôÐÔ´´½¨Ò»¸öÒÀÀµ¹ÜÀíʵÀý²¢ÉèÖÃÊôÐÔÃèÊö¶ÔÏó£¬ÔÚ´æÈ¡Æ÷º¯Êýgetº¯ÊýÖУ¬ÒÀÀµ¹ÜÀíʵÀýÌí¼Ó£¨¼Ç¼£©¸ÃÊôÐÔΪһ¸öÒÀÀµ£¬È»ºóµ±¸ÃÒÀÀµ±ä¸üʱ£¬´¥·¢setº¯Êý£¬Ôڸú¯ÊýÄÚ֪ͨÒÀÀµ¹ÜÀíʵÀý£¬ÒÀÀµ¹ÜÀíʵÀý·Ö·¢¸Ã±ä¸ü¸øÆäÄÚ´æ´¢µÄËùÓÐwatcherʵÀý£¬watcherʵÀýÖØÐ¼ÆË㣬¸üÐÂ×é¼þ¡£

Òò´Ë¿ÉÒÔ×ܽá˵Vue.jsµÄÏìӦʽԭÀíÊÇÒÀÀµ×·×Ù£¬Í¨¹ýÒ»¸ö¹Û²ì¶ÔÏó£¬ÎªÃ¿¸öÊôÐÔ£¬ÉèÖôæÈ¡Æ÷º¯Êý²¢×¢²áÒ»¸öÒÀÀµ¹ÜÀíʵÀýdep£¬depÄÚΪÿ¸ö×é¼þʵÀýά»¤Ò»¸öwatcherʵÀý£¬ÔÚÊôÐÔ±ä¸üʱ£¬Í¨¹ýsetter֪ͨdepʵÀý,depʵÀý·Ö·¢¸Ã±ä¸ü¸øÃ¿Ò»¸öwatcherʵÀý£¬watcherʵÀý¸÷×Ô¼ÆËã¸üÐÂ×é¼þʵÀý£¬¼´watcher×·×ÙdepÌí¼ÓµÄÒÀÀµ£¬Object.defineProperty()·½·¨ÌṩÕâÖÖ×·×ٵļ¼ÊõÖ§³Ö£¬depʵÀýά»¤ÕâÖÖ×·×Ù¹ØÏµ¡£

Ô´Âë¼òµ¥·ÖÎö

½ÓÏÂÀ´¶ÔVue.jsÔ´Âë½øÐмòµ¥·ÖÎö£¬´Ó¶ÔJavaScript¶ÔÏóºÍÊôÐԵĴ¦Àí¿ªÊ¼£º

¹Û²ì¶ÔÏó£¨OBSERVER£©

Ê×ÏÈ£¬Vue.jsÒ²ÌṩÁËÒ»¸ö³éÏó½Ó¿Ú¹Û²ì¶ÔÏó£¬Îª¶ÔÏóÊôÐÔÉèÖô洢Æ÷º¯Êý£¬ÊÕ¼¯ÊôÐÔÒÀÀµÈ»ºó·Ö·¢ÒÀÀµ¸üУº

var Observer = function Observer (value) {
this.value = value;
this.dep = new Dep(); // ¹ÜÀí¶ÔÏóÒÀÀµ
this.vmCount = 0;
def(value, '__ob__', this); // »º´æ´¦ÀíµÄ¶ÔÏó£¬

±ê¼Ç¸Ã¶ÔÏóÒÑ´¦Àí
if (Array.isArray(value)) {
var augment = hasProto
? protoAugment
: copyAugment;
augment(value, arrayMethods, arrayKeys);
this.observeArray(value);
} else {
this.walk(value);
}
};

ÉÏÃæ´úÂë¹Ø×¢Á½¸ö½Úµã£¬ this . observeArray(value) ºÍ this . walk (value) ;£º

ÈôΪ¶ÔÏó£¬Ôòµ÷ÓÃwalk()·½·¨£¬±éÀú¸Ã¶ÔÏóÊôÐÔ£¬½«ÊôÐÔת»»ÎªÏìӦʽ£º


Observer.prototype.walk = function walk (obj) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
defineReactive$$1(obj, keys[i], obj[keys[i]]);
}
};

¿ÉÒÔ¿´µ½£¬×îÖÕÉèÖÃÊôÐÔÃèÊö¶ÔÏóÊÇͨ¹ýµ÷Óà defineReactive$$1() ·½·¨¡£

ÈôvalueΪ¶ÔÏóÊý×飬ÔòÐèÒª¶îÍâ´¦Àí£¬µ÷Óà observeArray() ·½·¨¶Ôÿһ¸ö¶ÔÏó¾ù²úÉúÒ»¸ö Observer ʵÀý£¬±éÀú¼àÌý¸Ã¶ÔÏóÊôÐÔ£º


Observer.prototype.observeArray =

function observeArray (items) {
for (var i = 0, l = items.length; i < l; i++) {
observe(items[i]);
}
};

ºËÐÄÊÇΪÿ¸öÊý×éÏîµ÷ÓÃobserveº¯Êý£º


function observe(value, asRootData) {
if (!isObject(value)) {
return // Ö»ÐèÒª´¦Àí¶ÔÏó
}
var ob;
if (hasOwn(value, '__ob__') && value.__

ob__ instanceof Observer) {
ob = value.__ob__; // ´¦Àí¹ýµÄÔòÖ±½Ó¶ÁÈ¡»º´æ
} else if (
observerState.shouldConvert &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue) {
ob = new Observer(value); // ´¦Àí¸Ã¶ÔÏó
}
if (asRootData && ob) {
ob.vmCount++;
}
return ob
}

µ÷ÓÃob = new Observer(value) ;ºó¾Í»Øµ½µÚÒ»ÖÖÇé¿öµÄ½á¹û£ºµ÷ÓÃd efineReactive$$1() ·½·¨Éú³ÉÏìӦʽÊôÐÔ¡£

Éú³ÉÏìӦʽÊôÐÔ

Ô´ÂëÈçÏ£º

function defineReactive$$1 (obj,key,

val,customSetter) {
var dep = new Dep(); // ¹ÜÀíÊôÐÔÒÀÀµ

var property = Object.getOwnProperty

Descriptor(obj, key);
if (property && property.configurable

=== false) {
return
}

// ֮ǰÒѾ­ÉèÖÃÁ˵Äget/setÐèÒªºÏ²¢µ÷ÓÃ
var getter = property && property.get;
var setter = property && property.set;

var childOb = observe(val); // ÊôÐÔÖµÒ²¿ÉÄÜ

ÊǶÔÏó£¬ÐèÒªµÝ¹é¹Û²ì´¦Àí
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
var value = getter ? getter.call(obj) : val;
if (Dep.target) { // ¹ÜÀíÒÀÀµ¶ÔÏó´æÔÚÖ¸ÏòµÄ

watcherʵÀý
dep.depend(); // Ìí¼ÓÒÀÀµ£¨¼Ç¼£©
if (childOb) { // ÊôÐÔֵΪ¶ÔÏó
childOb.dep.depend(); // ÊôÐÔÖµ¶ÔÏóÒ²ÐèÒª

Ìí¼ÓÒÀÀµ
}
if (Array.isArray(value)) {
dependArray(value); // ´¦ÀíÊý×é
}
}
return value
},
set: function reactiveSetter (newVal) {
var value = getter ? getter.call(obj) : val;
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal

&& value !== value)) {
return // δ·¢Éú±ä¸ü²»ÐèÒªÍùºóÖ´ÐÐ
}
/* eslint-enable no-self-compare */
if ("development" !== 'production' &&

customSetter) {
customSetter();
}
if (setter) {
setter.call(obj, newVal); // ¸üÐÂÊôÐÔÖµ
} else {
val = newVal; // ¸üÐÂÊôÐÔÖµ
}
childOb = observe(newVal); // ÿ´ÎÖµ±ä¸üʱÐèÒª

ÖØÐ¹۲죬ÒòΪ¿ÉÄÜֵΪ¶ÔÏó
dep.notify(); // ·¢²¼¸üÐÂʼþ
}
});
}

¸Ã·½·¨Ê¹Óà Object . defineProperty() ·½·¨ÉèÖÃÊôÐÔÃèÊö¶ÔÏó£¬Âß¼­¼¯ÖÐÔÚÊôÐÔ´æÈ¡Æ÷º¯ÊýÄÚ£º

1.get: ·µ»ØÊôÐÔÖµ£¬Èç¹ûwatcher´æÔÚ£¬ÔòµÝ¹é¼Ç¼ÒÀÀµ£»

2.set: ÊôÐÔÖµ·¢Éú±ä¸üʱ£¬¸üÐÂÊôÐÔÖµ£¬²¢µ÷ÓÃdep.notify()·½·¨·¢²¼¸üÐÂʼþ£»

¹ÜÀíÒÀÀµ

Vue.jsÐèÒª¹ÜÀí¶ÔÏóµÄÒÀÀµ£¬ÔÚÊôÐÔ¸üÐÂʱ֪ͨwatcher¸üÐÂ×é¼þ£¬½ø¶ø¸üÐÂÊÓͼ£¬Vue.js¹ÜÀíÒÀÀµ½Ó¿Ú²ÉÓ÷¢²¼¶©ÔÄģʽʵÏÖ£¬Ô´ÂëÈçÏ£º

var uid$1 = 0;
var Dep = function Dep () {
this.id = uid$1++; // ÒÀÀµ¹ÜÀíʵÀýid
this.subs = []; // ¶©ÔĸÃÒÀÀµ¹ÜÀíʵÀýµÄwatcherʵÀýÊý×é
};
Dep.prototype.depend = function depend () { // Ìí¼ÓÒÀÀµ
if (Dep.target) {
Dep.target.addDep(this); // µ÷ÓÃwatcherʵÀý·½·¨¶©ÔÄ´ËÒÀÀµ¹ÜÀíʵÀý
}
};
Dep.target = null; // watcherʵÀý
var targetStack = []; // ά»¤watcherʵÀýÕ»

function pushTarget (_target) {
if (Dep.target) { targetStack.push(Dep.target); }
Dep.target = _target; // ³õʼ»¯DepÖ¸ÏòµÄwatcherʵÀý
}

function popTarget () {
Dep.target = targetStack.pop();
}

¶©ÔÄ

Èç֮ǰ£¬Éú³ÉÏìӦʽÊôÐÔΪÊôÐÔÉèÖôæÈ¡Æ÷º¯Êýʱ£¬getº¯ÊýÄÚµ÷Óà dep . depend () ·½·¨Ìí¼ÓÒÀÀµ£¬¸Ã·½·¨ÄÚµ÷Óà Dep . target . addDep (this) ;£¬¼´µ÷ÓÃÖ¸ÏòµÄ watcher ʵÀýµÄ addDep ·½·¨£¬¶©ÔÄ´ËÒÀÀµ¹ÜÀíʵÀý£º


Watcher.prototype.addDep = function addDep (dep) {
var id = dep.id;
if (!this.newDepIds.has(id)) { // ÊÇ·ñÒѶ©ÔÄ
this.newDepIds.add(id); // watcher

ʵÀýά»¤µÄÒÀÀµ¹ÜÀíʵÀýid¼¯ºÏ
this.newDeps.push(dep); // watcher

ʵÀýά»¤µÄÒÀÀµ¹ÜÀíʵÀýÊý×é
if (!this.depIds.has(id)) { // watcher

ʵÀýά»¤µÄÒÀÀµ¹ÜÀíʵÀýid¼¯ºÏ
// µ÷Óô«µÝ¹ýÀ´µÄÒÀÀµ¹ÜÀíʵÀý·½·¨£¬

Ìí¼Ó´ËwatcherʵÀýΪ¶©ÔÄÕß
dep.addSub(this);
}
}
};

watcherʵÀý¿ÉÄÜͬʱ׷×Ù¶à¸öÊôÐÔ£¨¼´¶©ÔĶà¸öÒÀÀµ¹ÜÀíʵÀý£©£¬ËùÒÔÐèҪά»¤Ò»¸öÊý×飬´æ´¢¶à¸ö¶©ÔĵÄÒÀÀµ¹ÜÀíʵÀý£¬Í¬Ê±¼Ç¼ÿһ¸öʵÀýµÄid£¬±ãÓÚÅжÏÊÇ·ñÒѶ©ÔÄ£¬¶øºóµ÷ÓÃÒÀÀµ¹ÜÀíʵÀýµÄ addSub ·½·¨£º


Dep.prototype.addSub = function addSub (sub) {
this.subs.push(sub); // ʵÏÖwatcherµ½ÒÀÀµ¹ÜÀíʵÀýµÄ¶©ÔĹØÏµ
};

¸Ã·½·¨Ö»ÊǼòµ¥µÄÔÚ¶©ÔÄÊý×éÄÚÌí¼ÓÒ»¸ö¶©ÔĸÃÒÀÀµ¹ÜÀíʵÀýµÄ watcher ʵÀý¡£

·¢²¼

ÊôÐÔ±ä¸üʱ£¬ÔÚÊôÐԵĴæÈ¡Æ÷setº¯ÊýÄÚµ÷ÓÃÁË dep.notify() ·½·¨£¬·¢²¼´ËÊôÐÔ±ä¸ü£º

Dep.prototype.notify = function notify () {
// ¸´Öƶ©ÔÄÕßÊý×é
var subs = this.subs.slice();
for (var i = 0, l = subs.length; i < l; i++) {
subs[i].update(); // ·Ö·¢±ä¸ü
}
};

´¥·¢¸üÐÂ

Ç°ÃæÌáµ½£¬Vue.jsÖÐÓÉwatcher²ã×·×ÙÒÀÀµ±ä¸ü£¬·¢Éú±ä¸üʱ£¬Í¨Öª×é¼þ¸üУº


Watcher.prototype.update = function update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true;
} else if (this.sync) { // ͬ²½
this.run();
} else { // Òì²½
queueWatcher(this); // ×îºóÒ²Êǵ÷ÓÃrun()·½·¨
}
};

µ÷ÓÃrun·½·¨£¬Í¨Öª×é¼þ¸üУº

Watcher.prototype.run = function run () {
if (this.active) {
var value = this.get(); // »ñÈ¡ÐÂÊôÐÔÖµ
if (value !== this.value || // ÈôÖµ
isObject(value) || this.deep) {
var oldValue = this.value; // »º´æ¾ÉÖµ
this.value = value; // ÉèÖÃÐÂÖµ
if (this.user) {
try {
this.cb.call(this.vm, value, oldValue);
} catch (e) {
handleError(e, this.vm, ("callback for watcher \"" + (this.expression) + "\""));
}
} else {
this.cb.call(this.vm, value, oldValue);
}
}
}
};

µ÷ÓÃthis.get()·½·¨£¬Êµ¼ÊÉÏ£¬ºóÃæ»á¿´µ½Ôڸ÷½·¨ÄÚ´¦ÀíÁËÊôÐÔÖµµÄ¸üÐÂÓë×é¼þµÄ¸üУ¬ÕâÀïÅжϵ±ÊôÐÔ±ä¸üʱµ÷Óóõʼ»¯Ê±´«¸øÊµÀýµÄcb»Øµ÷º¯Êý£¬²¢Çһص÷º¯Êý½ÓÊÜÊôÐÔоÉÖµÁ½¸ö²ÎÊý£¬´Ë»Øµ÷ͨ³£ÊǶÔÓÚwatchÉùÃ÷µÄ¼àÌýÊôÐÔ²Å»á´æÔÚ£¬·ñÔòĬÈÏΪ¿Õº¯Êý¡£

×·×ÙÒÀÀµ½Ó¿ÚʵÀý»¯

ÿһ¸öÏìӦʽÊôÐÔ¶¼ÊÇÓÉÒ»¸öWatcherʵÀý×·×ÙÆä±ä¸ü£¬¶øÕë¶Ô²»Í¬ÊôÐÔ£¨ data , computed , watch £©£¬Vue.js½øÐÐÁËһЩ²îÒì´¦Àí£¬ÈçÏÂÊǽӿÚÖ÷ÒªÂß¼­£º

var Watcher = function Watcher (vm,expOrFn,cb,options) {
this.cb = cb;
...
// parse expression for getter
if (typeof expOrFn === 'function') {
this.getter = expOrFn;
} else {
this.getter = parsePath(expOrFn);
}
this.value = this.lazy
? undefined
: this.get();
};

ÔÚ³õʼ»¯WatcherʵÀýʱ£¬»á½âÎöexpOrFn²ÎÊý£¨±í´ïʽ»òÕߺ¯Êý£©³ÉÍØÕ¹ getterthis.getter £¬È»ºóµ÷ÓÃthis.get£¨£©·½·¨£¬·µ»ØÖµ×÷Ϊthis.valueÖµ£º

Watcher.prototype.get = function get () {
pushTarget(this); // ÈëÕ»watcherʵÀý
var value;
var vm = this.vm;
if (this.user) {
try {
value = this.getter.call(vm, vm); // ͨ¹ýthis.getter»ñÈ¡ÐÂÖµ
} catch (e) {
handleError(e, vm, ("getter for watcher \"" +
(this.expression) + "\""));
}
} else {
value = this.getter.call(vm, vm); // ͨ¹ýthis.getter»ñÈ¡ÐÂÖµ
}

if (this.deep) { // Éî¶ÈµÝ¹é±éÀú¶ÔÏó×·×ÙÒÀÀµ
traverse(value);
}
popTarget(); // ³öÕ»watcherʵÀý
this.cleanupDeps(); // Çå¿Õ»º´æÒÀÀµ
return value // ·µ»ØÐÂÖµ
};

ÕâÀïÐèҪעÒâµÄÊǶÔÓÚdataÊôÐÔ£¬¶ø·ÇcomputedÊôÐÔ»òwatchÊôÐÔ£¬¶øÑÔ£¬ÆäwatcherʵÀýµÄthis.getterͨ³£¾ÍÊÇupdateComponentº¯Êý£¬¼´äÖȾ¸üÐÂ×é¼þ£¬get·½·¨·µ»Øundefined£¬¶ø¶ÔÓÚcomputed¼ÆËãÊôÐÔ¶øÑÔ£¬»á´«Èë¶ÔÓ¦Ö¸¶¨º¯Êý¸øthis.getter£¬Æä·µ»ØÖµ¾ÍÊÇ´Ëget·½·¨·µ»ØÖµ¡£

dataÆÕͨÊôÐÔ

Vue.jsdataÊôÐÔÊÇÒ»¸ö¶ÔÏó£¬ÐèÒªµ÷ÓöÔÏó¹Û²ì½Ó¿Ú new Observer (value) £º


function observe (value, asRootData) {
if (!isObject(value)) {
return
}
var ob;
ob = new Observer(value); // ¶ÔÏó¹Û²ìʵÀý
return ob;
}

// ³õʼ´¦ÀídataÊôÐÔ
function initData (vm) {
// µ÷ÓÃobserveº¯Êý
observe(data, true /* asRootData */);
}

¼ÆËãÊôÐÔ

Vue.js¶Ô¼ÆËãÊôÐÔ´¦ÀíÊÇÓвîÒìµÄ£¬ËüÊÇÒ»¸ö±äÁ¿£¬¿ÉÒÔÖ±½Óµ÷ÓÃWatcher½Ó¿Ú£¬°ÑÆäÊôÐÔÖ¸¶¨µÄ¼ÆËã¹æÔò´«µÝΪ£¬ÊôÐÔµÄÍØÕ¹getter£¬¼´£º


// ³õʼ´¦Àícomputed¼ÆËãÊôÐÔ
function initComputed (vm, computed) {
for (var key in computed) {
var userDef = computed[key]; // ¶ÔÓ¦µÄ¼ÆËã¹æÔò
// ´«µÝ¸øwatcherʵÀýµÄthis.getter -- ÍØÕ¹getter
var getter = typeof userDef === 'function' ?
userDef : userDef.get;
watchers[key] = new Watcher(vm,
getter, noop, computedWatcherOptions);
}
}

watchÊôÐÔ

¶ø¶ÔÓÚwatchÊôÐÔÓÖÓв»Í¬£¬¸ÃÊôÐÔÊDZäÁ¿»ò±í´ïʽ£¬¶øÇÒÓë¼ÆËãÊôÐÔ²»Í¬µÄÊÇ£¬ËüÐèÒªÖ¸¶¨Ò»¸ö±ä¸üʼþ·¢ÉúºóµÄ»Øµ÷º¯Êý£º


function initWatch (vm, watch) {
for (var key in watch) {
var handler = watch[key];
createWatcher(vm, key, handler[i]); // ´«µÝ»Øµ÷
}
}
function createWatcher (vm, key, handler) {
vm.$watch(key, handler, options); // »Øµ÷
}
Vue.prototype.$watch = function (expOrFn, cb, options) {
// ʵÀý»¯watcher£¬²¢´«µÝ»Øµ÷
var watcher = new Watcher(vm, expOrFn, cb, options);
}

³õʼ»¯WatcherÓëÒÀÀµ¹ÜÀí½Ó¿ÚµÄÁ¬½Ó

ÎÞÂÛÄÄÖÖÊôÐÔ×îºó¶¼ÊÇÓÉwatcher½Ó¿ÚʵÏÖ×·×ÙÒÀÀµ£¬¶øÇÒ×é¼þÔÚ¹ÒÔØÊ±£¬¼´»á³õʼ»¯Ò»´ÎWatcherʵÀý£¬°ó¶¨µ½Dep.target£¬Ò²¾ÍÊǽ«WatcherºÍDep½¨Á¢Á¬½Ó£¬Èç´ËÔÚ×é¼þäÖȾʱ²ÅÄܶÔÊôÐÔÒÀÀµ½øÐÐ×·×Ù£º

function mountComponent (vm, el, hydrating) {
...
updateComponent = function () {
vm._update(vm._render(), hydrating);
...
};
...
vm._watcher = new Watcher(vm, updateComponent, noop);
...
}

ÈçÉÏ£¬´«µÝ updateComponent ·½·¨¸ø watcher ʵÀý£¬¸Ã·½·¨ÄÚ´¥·¢×é¼þʵÀýµÄ vm._render() äÖȾ·½·¨£¬´¥·¢×é¼þ¸üУ¬´Ë mountComponent() ·½·¨»áÔÚ$mount()¹ÒÔØ×é¼þ¹«¿ª·½·¨Öе÷Óãº


// public mount method
Vue$3.prototype.$mount = function (el, hydrating) {
el = el && inBrowser ? query(el) : undefined;
return mountComponent(this, el, hydrating)
};

×ܽá

µ½´ËΪֹ£¬¶ÔÓÚJavaScriptÊôÐÔÃèÊöÆ÷½Ó¿ÚµÄ½éÉܼ°ÆäÓ¦Ó㬻¹ÓÐÆäÔÚVue.jsÖеÄÏìӦʽʵ¼ùÔ­Àí»ù±¾²ûÊöÍêÁË£¬Õâ´Î×ܽá´ÓÔ­Àíµ½Ó¦Óã¬ÔÙµ½Êµ¼ùÆÊÎö£¬»¨·Ñ±È½Ï¶à¾«Á¦£¬µ«ÊÇÊÕ»ñÊdzÉÕý±ÈµÄ£¬²»½ö¶ÔJavaScript»ù´¡ÓиüÉîµÄÀí½â£¬»¹¸üÊìϤÁËVue.jsÏìӦʽµÄÉè¼ÆÔ­Àí£¬¶ÔÆäÔ´ÂëÊìϤ¶ÈÒ²ÓнϴóÌáÉý£¬Ö®ºóÔÚ¹¤×÷ºÍѧϰ¹ý³ÌÖУ¬»á½øÐиü¶àµÄ×ܽá·ÖÏí¡£

   
1977 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì