Program Club

표현을 '감시 해제'하는 방법

proclub 2020. 11. 1. 19:01
반응형

표현을 '감시 해제'하는 방법


큰 배열로 ng-repeat가 있다고 가정하십시오.

ng-repeat가 실행되면 해당 배열의 모든 요소가 격리 된 범위에 추가되고 배열 자체가 범위에 포함됩니다. 즉, $ digest는 전체 배열의 변경 사항을 확인 하고 그 외에도 해당 배열의 모든 개별 요소 가 변경 되었는지 확인 합니다 .

참조 이 plunker을 내가 무슨 말의 예로서.

내 사용 사례에서는 배열의 단일 요소를 절대 변경하지 않으므로 그들을 지켜 볼 필요가 없습니다. 나는 전체 배열 만 변경할 것이며,이 경우 ng-repeat는 테이블 전체를 다시 렌더링합니다. (내가 틀렸다면 알려주세요 ..)

(예를 들어) 1000 행의 배열에서, 그것은 내가 평가할 필요가없는 1000 개 이상의 표현식입니다.

주 배열을 계속 보면서 감시자에서 각 요소를 어떻게 등록 취소 할 수 있습니까?

등록을 취소하는 대신 $ digest를 더 많이 제어하고 어떻게 든 각 개별 행을 건너 뛸 수 있습니까?

이 특정 사례는 실제로 더 일반적인 문제의 예입니다. $ watch가 '등록 취소'함수를 반환 한다는 것을 알고 있지만 대부분의 경우 지시문이 시계를 등록하는 경우에는 도움이되지 않습니다.


모든 항목을보기 위해 보지 않는 큰 배열이있는 중계기를 갖기 위해.

하나의 인수와 배열에 대한 표현식을 사용하는 사용자 지정 지시문을 만들어야합니다. 그런 다음 연결 함수에서 해당 배열을 확인하고 연결 함수를 사용하여 HTML을 프로그래밍 방식으로 새로 고치게됩니다. ng- 반복)

(의사 코드) :

app.directive('leanRepeat', function() {
    return {
        restrict: 'E',
        scope: {
           'data' : '='
        },
        link: function(scope, elem, attr) {
           scope.$watch('data', function(value) {
              elem.empty(); //assuming jquery here.
              angular.forEach(scope.data, function(d) {
                  //write it however you're going to write it out here.
                  elem.append('<div>' + d + '</div>');
              });
           });
        }
    };
});

... 엉덩이에 통증이있는 ​​것 같습니다.

대체 해킹 방법

당신은을 통해 루프 수있을 $scope.$$watchers및 검사 $scope.$$watchers[0].exp.exp당신이 다음, 제거하는 간단한 그것을 제거하고자하는 표현과 일치하는지 확인하기 위해 splice()호출. 여기서 PITA Blah {{whatever}} Blah는 태그 사이 와 같은 것이 표현식이 될 것이며 캐리지 리턴도 포함 한다는 것 입니다.

좋은 점은 ng-repeat의 $ 범위를 반복하고 모든 것을 제거한 다음 원하는 시계를 명시 적으로 추가 할 수 있다는 것입니다.

어느 쪽이든 해킹처럼 보입니다.

$ scope. $ watch에서 만든 감시자를 제거하려면

호출에서 $watch반환 된 함수를 사용하여 등록을 취소 할 수 있습니다 $watch.

예를 들어, $watch한 번만 불을 피우 려면 :

var unregister = $scope.$watch('whatever', function(){ 
     alert('once!');
     unregister();
});

물론 원할 때 언제든지 등록 해제 기능을 호출 할 수 있습니다. 이는 단지 예일뿐입니다.

결론 : 당신이 요구하는 것을 정확히 할 수있는 좋은 방법은 없습니다.

그러나 한 가지 고려해야 할 사항은 걱정할 가치가 있습니까? 또한 수천 개의 레코드를 각각 수십 개의 DOMElement에로드하는 것이 정말 좋은 생각입니까? 생각할 거리.

도움이 되었기를 바랍니다.


편집 2 (나쁜 아이디어 제거)


$ watch는 호출 될 때 $ watch의 바인딩을 해제하는 함수를 반환합니다. 따라서 "watchOnce"에 필요한 것은 다음과 같습니다.

var unwatchValue = scope.$watch('value', function(newValue, oldValue) {
  // Do your thing
  unwatchValue();
});

편집 : 내가 게시 한 다른 답변을 참조하십시오.

나는 블레 쉬의 아이디어를 분리 가능한 방식으로 구현했습니다. ngOnce지시문 ngRepeat은 각 항목에 생성 되는 자식 범위를 파괴합니다 . 이것은 범위가 부모로부터 도달하지 않고 scope.$digest감시자가 실행 되지 않음을 의미합니다 .

Source and example on JSFiddle

The directive itself:

angular.module('transclude', [])
 .directive('ngOnce', ['$timeout', function($timeout){
    return {
      restrict: 'EA',
      priority: 500,
      transclude: true,
      template: '<div ng-transclude></div>',
        compile: function (tElement, tAttrs, transclude) {
            return function postLink(scope, iElement, iAttrs, controller) {
                $timeout(scope.$destroy.bind(scope), 0);
            }
        }
    };
}]);

Using it:

      <li ng-repeat="item in contents" ng-once>
          {{item.title}}: {{item.text}}
      </li>

Note ng-once doesn't create its own scope which means it can affect sibling elements. These all do the same thing:

  <li ng-repeat="item in contents" ng-once>
      {{item.title}}: {{item.text}}
  </li>
  <li ng-repeat="item in contents">
      <ng-once>
          {{item.title}}: {{item.text}}
      </ng-once>
  </li>
  <li ng-repeat="item in contents">
      {{item.title}}: {{item.text}} <ng-once></ng-once>
  </li>

Note this may be a bad idea


You can add the bindonce directive to your ng-repeat. You'll need to download it from https://github.com/pasvaz/bindonce.

edit: a few caveats:

If you're using {{}} interpolation in your template, you need to replace it with <span bo-text>.

If you're using ng- directives, you need to replace them with the right bo- directives.

Also, if you're putting bindonce and ng-repeat on the same element, you should try either moving the bindonce to a parent element (see https://github.com/Pasvaz/bindonce/issues/25#issuecomment-25457970 ) or adding track by to your ng-repeat.


If you are using angularjs 1.3 or above, you can use the single bind syntax as

<li ng-repeat="item in ::contents">{{item}}</li>

This will bind the value and will remove the watchers once the first digest cycle is run and the value changes from undefined to defined for the first time.

A very helpful BLOG on this.

참고URL : https://stackoverflow.com/questions/13651578/how-to-unwatch-an-expression

반응형