AngularJS-첫 번째 부분 Scopes 만들기 (3)

3477 단어

값 기반 Dirty 검사


지금까지 우리는 이미 엄격한 상등 조작부호===를 사용하여 신구 값을 비교하였다.대부분의 경우, 이것은 이미 비교적 좋은 것이다. 왜냐하면 모든 기본 유형의 변화를 측정할 수 있을 뿐만 아니라, 한 대상이나 그룹이 다른 새로운 대상이나 그룹이 되었는지 검사할 수 있기 때문이다.그러나 Angular는 대상이나 그룹 내부의 어떤 속성이나 요소의 변화를 측정하는 또 다른 방식을 가지고 있다.인용만 있는 것이 아니라 값의 변화를 감시할 수 있다는 얘기다.
이dirty 검사는 $watch 함수에 선택할 수 있는 볼 로고를 추가로 제공하는 것을 통해 이루어집니다.로고가true일 때 값 기반 체크가 활성화됩니다.다음 테스트를 추가합니다.
test/scope_spec.js
it("conpares based on value if enabled",function(){
  scope.aValue = [1,2,3];
  scope.counter = 0 ;

  scope.$watch(
    function(scope){ return scope.aValue; }
    function(newValue,oldValue,scope){
      scope.counter++;
    },
    true
  );

  scope.$digest();
  expect(scope.counter).toBe(1);

  scope.aValue.push(4);
  scope.$digest();
  expect(scope.counter).toBe(2);
});

이 테스트에서 스코프를 막론하고.AValue 수조는 언제 바뀌어도 계수기가 늘어납니다.우리가 수조에 원소를 추가할 때, 우리는 그것이 이 변화에 주의할 수 있기를 기대하지만, 실제로는 그렇지 않다.scope.AValue는 여전히 같은 그룹입니다. 단지 안의 내용에 변화가 생겼을 뿐입니다. (인용은 변하지 않았고 값은 변화가 생겼습니다.)
먼저 $watch가 부울 값을 추가하는 표지 위치를 다시 정의하고 모니터에 저장합니다.
src/scope.js
Scope.prototype.$watch = function(watchFn,listenerFn,valueEq){
  var watcher = {
    watchFn : watchFn,
    listenerFn : listenerFn || function(){},
    valueEq : !!valueEq,
    last : initWatchVal
  };
  this.$$watchers.push(watcher);
  this.$$lastDirtyWatch = null;
};

위 코드에서, 우리가 하는 일은 모니터에 브리 로고 위치를 추가하고, 두 번의 역조작을 통해 브리 값이 반드시 브리 값이어야 한다는 것을 강제로 확보하는 것이다.사용자가 $watch를 호출하여 세 번째 인자를 만들지 않았을 때,valueEq는undefined이고, 두 번의 리셋을 통해false가 됩니다.
값 기반dirty 검사는 이전 값이나 새 값이 대상이나 수조라면 모든 속성이나 요소를 교체해야 한다는 것을 의미합니다.만약 그것들의 값이 다른 점이 있다면 모니터는dirty이다.만약 값이 다른 대상이나 그룹을 포함한다면, 이 대상이나 그룹은 비슷한 비교 값을 되돌려받을 것이다.
Angular는 자체 비교 검사 함수를 사용하지만, 우리는 Lo-dash에서 제공하는 함수를 대체할 것입니다. 왜냐하면 이것은 우리가 원하는 기능을 실현했기 때문입니다.두 개의 값과 하나의 부울 ID를 매개변수로 사용하는 새 함수를 정의하고 두 값을 비교합니다.
src/scope.js
Scope.prototype.$$areEqual = function(newValue,oldValue,valueEq){
  if(valueEq){
    return _.isEqual(newValue,oldValue);
  }else{
    return newValue === oldValue;
  }
}

값의 변화를 주의하기 위해서, 우리는 각 모니터에 오래된 값을 저장하는 방식을 바꾸어야 한다.현재 값만 저장하는 인용은 분명히 부족합니다. 값에 대한 어떠한 변화도 우리의 감시에 적용될 수 있기 때문입니다.$$areEqual은 처음부터 두 개의 인용을 받을 것이며, 두 인용의 값이 바뀌지 않기 때문에 변경 사항은 영원히 알 수 없습니다.이 때문에 우리는 값을 심도 있게 복사해서 저장해야 한다.
Angular가 자신의 깊은 복사 함수를 사용하여 같은 검사를 하는 것처럼, 현재 우리는 Lo-dash의 한 방법을 사용하여 실현할 것이다.
$digestOnce를 업데이트하여 새 $$$areEqual 함수를 사용하고 마지막 참조를 복사합니다.
src/scope.js
Scope.prototype.$$digestOnce = function(){
  var self = this;
  var newValue,oldValue,dirty;
  
  _.forEach(this.$$watchers,function(watcher){
    newValue = watcher.watchFn(self);
    oldValue = watcher.last;
    if(!self.$$areEqual(newValue,oldValue,watcher.valueEq)){
      self.$$lastDirtyWatch = watcher;
      watcher.last = (watcher.valueEq ? _.cloneDeep(newValue) : newValue);
      watcher.listenerFn(newValue,
        (oldValue === initWatchVal ? newValue : oldValue),
        self);
        dirty = true;
    }else if(self.$$lastDirtyWatch === watcher){
      return false;
    }
  });
  return dirty;
}

테스트가 통과되었습니다. 현재 우리의 코드는 이미 두 종류의 동일한 검사를 지원합니다.
검사 값의 조작은 인용을 검사하는 조작보다 분명히 더 복잡하다.관련된 내용도 더 많다.중첩된 데이터를 검사하는 데 걸리는 시간, 깊은 복사를 하는 데 사용되는 메모리 크기.이것이 바로 Angular가 기본적으로 값 기반dirty 검사를 하지 않는 이유입니다.로고를 현저하게 설정해서 사용해야 합니다.
Angular에는 세 번째dirty 검사 메커니즘인 컬렉션 모니터링(Collection Watching)도 있습니다.우리는 3장에서 그것을 실현할 것이다.
값을 비교하기 전에 JavaScript만의 고유한 문제를 처리해야 합니다.

좋은 웹페이지 즐겨찾기