vueの配列リスニング
21086 ワード
Vueでのデータの傍受は主に
一、配列の変化状況:配列自体の付与 配列における 配列における値変化 動作配列の長さによる変化 二、上の変化を順次分析する.
配列自体の割り当て
この場合,オブジェクトの傍受と一致し,
配列におけるpushなどの方法による変化
配列は、 pushなどの方法は、 .このとき、
完全なコード:
参照ドキュメント:http://www.qiutianaimeili.com/html/page/2019/05/m0kcbzlpc9s.html https://www.cnblogs.com/DevinnZ/p/10569033.html
Object.defineProperty
によって実現され、このような実現は主にkey/value
形式のオブジェクトに対して、配列中の値の変化に対して無力であり、definrProperty
は配列長の変化を傍受することができず、傍受インデックスの代価も高い.では、どのように配列中のデータを傍受すべきか.一、配列の変化状況:
push
等の方法による変化配列自体の割り当て
この場合,オブジェクトの傍受と一致し,
defineProperty
を直接用いてデータを傍受すればよい.配列におけるpushなどの方法による変化
配列
push
等の操作によりデータが変更された場合に傍受したいデータの変化はdefineProperty
では実現できない.どうやって実現するの?Object.create
によってArray.prototype
の後継者arraymethods
を実現する必要がある.アクセス方法とArray.prototypeは同じです.私たちは直接Arrayにいることはできません.prototypeでは、通常のメソッドの呼び出しに影響を与えるため、メソッドをリスニングします.defineproperty
を介してarraymethods
オブジェクトに直接書き込む:const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'reverse',
'sort'
];
const arrayProto = Array.prototype, // Array
arrayMethods = Object.create(arrayProto); // Array
//
function def(obj, key, val) {
Object.defineProperty(obj, key, {
value: val,
enumerable: true,
writable: true,
configurable: true
});
}
methodsToPatch.forEach(function(method, index) {
def(arrayMethods, method, function(...args) {
//arrayProto[method].apply(this, args);
});
});
arraymethods
の7つのメソッドに直接アクセスすると、arraymethods
のオブジェクトに直接アクセスし、内部にarrayProto[method].apply(this,args)
を介して配列上の本当のメソッドにアクセスするリスニングが必要なメソッドを書くことができます.arraymethods
は私たちが構築した構造であり、それ自体が配列ではないので、私たちが操作している配列に対して、本当のarraymethods
の方法ではなく、Array.prototype
の方法を指すようにします.if('__proto__' in {}) {
// __proto__, arrayMethods, 7 , arrayMethods Array.prototype
target.__proto__ = arrayMethods;
} else {
// __proto__, arraymethods 。 , 7 ,
for(let i = 0, l = methodsToPatch.length; i < l; i++) {
let key = methodsToPatch[i];
def(target, key, arrayMethods[key]);
}
}
完全なコード:
const patchArray = (function() {
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'reverse',
'sort'
];
//
function def(obj, key, val) {
Object.defineProperty(obj, key, {
value: val,
enumerable: true,
writable: true,
configurable: true
});
}
const arrayProto = Array.prototype, // Array
arrayMethods = Object.create(arrayProto); // Array
methodsToPatch.forEach(function(method, index) {
def(arrayMethods, method, function(...args) {
// Array
const old=this.concat([]);
const res = arrayProto[method].apply(this, args);
let inserted = null,
deleted = null;
let _callback_ = this._callback_;
//
switch(method) {
case 'push':
case 'unshift':
inserted = args;
break;
case 'splice':
//
inserted = args.slice(2);
let start = args[0],
end = start + args[1];
deleted = old.slice(start, end);
break;
case 'pop':
case 'shift':
deleted = res;
}
_callback_(inserted, deleted);
return res;
});
});
return function(target, callback) {
def(target, '_callback_', callback); //
// __proto__ , __proto__ ,
if('__proto__' in {}) {
// arrayMethods, 7 , arrayMethods Array.prototype
target.__proto__ = arrayMethods;
} else {
// __proto__, , 7 ,
for(let i = 0, l = methodsToPatch.length; i < l; i++) {
let key = methodsToPatch[i];
def(target, key, arrayMethods[key]);
}
}
}
})();
//
let arr = [1, 2, 3];
patchArray(arr, function(add, del) {
if(add)
console.log(' :', add);
if(del)
console.log(' :', del);
});
arr.splice(1,2,'aa','bb','cc')
参照ドキュメント:http://www.qiutianaimeili.com/html/page/2019/05/m0kcbzlpc9s.html https://www.cnblogs.com/DevinnZ/p/10569033.html