Vue 감청 배열 변화 소스 분석
이 편 은 배열 의 문 제 를 고려 하기 시작 했다.
가장 쉬 운 것 부터 시작 하 다
한 가지 문 제 를 먼저 고려 하고,어떻게 배열 의 대상 변 화 를 감청 합 니까?배열 자체 와 그 중의 일반 값 을 무시 하고 대상 배열 의 대상 만 고려 합 니 다.
배열 을 옮 겨 다 니 며 배열 의 모든 대상 에 observe 방법 을 호출 합 니 다.
// ,
var Observer = function Observer(value) {
this.value = value;
this.dep = new Dep();
// ,
if(Array.isArray(value)) {
this.observeArray(value);
} else {
this.walk(value);
}
};
Observer.prototype.observeArray = function observeArray(items) {
// , getter、setter
for (var i = 0, l = items.length; i < l; i++) {
observe(items[i]);
}
};
현실 적 요구실제 실현 에서 전례 처럼 간단 하지 않 을 것 이다.공식 문서 에서 감청 배열 에 대해 이렇게 설명 했다.
Vue 는 배열 의 돌연 변 이 를 관찰 하 는 방법 을 포함 하기 때문에 보기 업 데 이 트 를 촉발 합 니 다.이 방법 들 은 다음 과 같다.
push()、pop()、shift()、unshift()、splice()、sort()、reverse()
JavaScript 의 제한 으로 인해 Vue 는 다음 과 같은 변 경 된 배열 을 감지 할 수 없습니다.
색인 을 직접 설정 할 때,예 를 들 어 vm.items[indexOfItem]=newValue
배열 의 길 이 를 수정 할 때,예 를 들 어 vm.items.length=newLength
그래서 배열 자체 의 방법 에 대해 감청 을 해 야 한다.
자주 사용 되 는 작은 함수
def,전체 Vue 소스 코드 에서 반복 적 으로 나타 납 니 다.Object.defineProperty()를 이용 하여 obj 에 속성 key 를 정의 합 니 다.(존재 하 는 속성 key 를 수정 할 수도 있 습 니 다.)
function def(obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
// boole , , false
enumerable: !!enumerable,
writable: true,
configurable: true
});
}
대상 에 그룹 추가 방법대상 에 게 그룹 방법 을 추가 합 니 다.환경 이 proto 를 지원 하면 간단 합 니 다.대상 의 proto 를 이 그룹 으로 가리 키 면 됩 니 다.지원 되 지 않 으 면 이 방법 을 옮 겨 다 니 며 대상 에 순서대로 추가 합 니 다.숨겨 진 속성(즉,enumerable:false,in 키워드 에서 찾 을 수 없습니다):
var hasProto = '__proto__' in {};
var augment = hasProto ? protoAugment : copyAugment;
function protoAugment(target, src) {
target.__proto__ = src;
}
function copyAugment(target, src, keys) {
for(var i = 0; i < keys.length; i++) {
var key = keys[i];
def(target, key, src[key]);
}
}
일단 쉬 운 거.
var arrayPush = {};
(function(method){
var original = Array.prototype[method];
arrayPush[method] = function() {
// this
console.log(this);
return original.apply(this, arguments)
};
})('push');
var testPush = [];
testPush.__proto__ = arrayPush;
// , this testPush
// []
testPush.push(1);
// [1]
testPush.push(2);
배열 의 변 화 를 감청 하기 위해 배열 의 원형 을 위조 하 다.공식 문서 에서 말 한 바 와 같이 감시 해 야 할 것 은 push(),pop(),shift(),unshift(),splice(),sort(),reverse()7 가지 방법 밖 에 없다.이 7 가지 방법 은 두 가지 로 나 눌 수 있다.
1.push(),unshift(),splice()세 가지 가 배열 에 새로운 요 소 를 추가 할 수 있 는 방법 입 니 다.
2.나머지 는 원 소 를 추가 하지 않 는 방법 입 니 다.
전역 을 오염 시 키 지 않도록 Array.prototype 을 원형 으로 하 는 대상 을 새로 만 든 다음 이 대상 자체 에 속성 을 추가 한 다음 에 이 새로 만 든 대상 을 원형 으로 하거나 Observer 의 value 에 속성 으로 추가 하여 변 화 를 감시 하 는 목적 을 달성 합 니 다.
var arrayProto = Array.prototype;
var arrayMethods = Object.create(arrayProto);
다음은 업데이트 가 필요 한 몇 가지 방법 을 옮 겨 다 니 며 array Methods 에 순서대로 추가 합 니 다.
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function(method) {
//
var original = arrayProto[method];
// arrayMethods method, method ( )
// arrayMethods
def(arrayMethods, method, function mutator() {
var arguments$1 = arguments;
var i = arguments.length;
var args = new Array(i);
// arguments
// [].slice.call(arguments)?
while(i--) {
args[i] = arguments$1[i];
}
var result = original.apply(this, args);
// arrayMethods Observer value , this Observer value
// , Observer, value Observer ,__ob__,
var ob = this.__ob__;
//
var inserted;
//
switch(method) {
case 'push':
inserted = args;
break;
case 'unshift':
inserted = args;
break;
case 'splice':
// splice
inserted =args.slice(2);
break;
}
if(inserted) {
// getter、setter
ob.observerArray(inserted);
}
//
ob.dep.notify();
return result;
});
};
var arrayKeys = Object.getOwnPropertyNames(arrayMethods);
Observer 업데이트상기 코드 의 주석 에 따라 Observer 를 바 꾸 어 이들 을 연결 시 켜 서 배열 변 화 를 감청 하 는 목적 을 달성 합 니 다.
var Observer = function Observer(value) {
this.value = value;
this.dep = new Dep();
def(value, '__ob__', this);
// ,
if(Array.isArray(value)) {
var argument = hasProto ? protoAugment : copyAugment;
argument(value, arrayMethods, arrayKeys);
this.observeArray(value);
} else {
this.walk(value);
}
};
참고 자료:vue 초기 소스 학습 시리즈 2:한 배열 의 변 화 를 어떻게 감청 합 니까?
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Vue Render 함수로 DOM 노드 코드 인스턴스 만들기render에서createElement 함수를 사용하여 DOM 노드를 만드는 것은 직관적이지 않지만 일부 독립 구성 요소의 디자인에서 특수한 수요를 충족시킬 수 있습니다.간단한 렌더링 예는 다음과 같습니다. 또한 v...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.