programing

AngularJS: 높이 변화를 관찰하는 더 좋은 방법

yoursource 2023. 3. 18. 14:18
반응형

AngularJS: 높이 변화를 관찰하는 더 좋은 방법

이전 가변 높이 내비게이션 문제가 있습니다.aposition: fixes맨 위의 네비게이션 및 콘텐츠margin-top: $naviHeight네비게이션은 데이터가 비동기적으로 로드될 때 높이가 변경될 수 있으므로 콘텐츠의 여백도 그에 따라 달라져야 합니다.

나는 이것이 스스로 억제되기를 바란다.따라서 데이터가 로드되는 코드는 없고 관련된 html 요소/지침에만 있습니다.

현재는 다음과 같은 타이머로 AngularJS 1.2.0으로 하고 있습니다.

/*
* Get notified when height changes and change margin-top
 */
.directive( 'emHeightTarget', function(){
    return {
        link: function( scope, elem, attrs ){

            scope.$on( 'heightchange', function( ev, newHeight ){

                elem.attr( 'style', 'margin-top: ' + (58+newHeight) + 'px' );
            } );
        }
    }
})

/*
* Checks this element periodically for height changes
 */
.directive( 'emHeightSource', ['$timeout', function( $timeout ) {

    return {
        link: function( scope, elem, attrs ){

            function __check(){

                var h = elem.height();

                if( h != scope.__height ){

                    scope.__height = h;
                    scope.$emit( 'heightchange', h );
                }
                $timeout( __check, 1000 );
            }
            __check();
        }
    }

} ] )

이것은 타이머를 사용하는 것의 명백한 결점(좀 못생겼다고 느껴짐)과 네비게이션 크기를 조정한 후 콘텐츠를 이동할 때까지의 일정 지연이 있습니다.

더 좋은 방법이 있을까요?

이는 워처를 에 등록함으로써 동작합니다.emHeightSource에브리라고 불리는$digest. 를 갱신합니다.__height차례로 감시되고 있는 재산emHeightTarget:

/*
 * Get notified when height changes and change margin-top
 */
.directive( 'emHeightTarget', function() {
    return {
        link: function( scope, elem, attrs ) {

            scope.$watch( '__height', function( newHeight, oldHeight ) {
                elem.attr( 'style', 'margin-top: ' + (58 + newHeight) + 'px' );
            } );
        }
    }
} )

/*
 * Checks every $digest for height changes
 */
.directive( 'emHeightSource', function() {

    return {
        link: function( scope, elem, attrs ) {

            scope.$watch( function() {
                scope.__height = elem.height();
            } );
        }
    }

} )

Div를 사용하지 않고 요소의 높이 변화를 모니터링할 수 있습니다.$watch스테이트먼트:

// Observe the element's height.
scope.$watch
    (
        function () {
            return linkElement.height();
        },
        function (newValue, oldValue) {
            if (newValue != oldValue) {
                // Do something ...
                console.log(newValue);
            }
        }
    );

아마 당신은 을 지켜봐야 할 것이다.$window치수는 다음과 같이 변화합니다.

.directive( 'emHeightSource', [ '$window', function(  $window ) {

    return {
        link: function( scope, elem, attrs ){

           var win = angular.element($window);
           win.bind("resize",function(e){

              console.log(" Window resized! ");
              // Your relevant code here...

           })
        }
    }    
} ] )

$watch 이벤트와 크기 조정 이벤트를 조합하여 사용했습니다.나는 범위 없이 찾았다.$watch(); 크기 조정 이벤트에서 요소의 높이 변경이 항상 $watch에 의해 인식되는 것은 아닙니다.

   link:function (scope, elem) {
        var win = angular.element($window);
        scope.$watch(function () {
                return elem[0].offsetHeight;
        },
          function (newValue, oldValue) {
              if (newValue !== oldValue)
              {
                  // do some thing
              }
          });

        win.bind('resize', function () {
            scope.$apply();
        });
    };

이 어프로치에 의해, (잠재적으로) 네트워크상의reflow모든 다이제스트 사이클확인만 됩니다.elem.height()// 다이제스트 사이클이 끝나면 높이가 변경된 경우에만 새 다이제스트가 발생합니다.

var DEBOUNCE_INTERVAL = 50; //play with this to get a balance of performance/responsiveness
var timer
scope.$watch(function() { timer = timer || $timeout(
    function() {
       timer = null;
       var h = elem.height();
       if (scope.height !== h) {
           scope.$apply(function() { scope.height = h })
       }
    },
    DEBOUNCE_INTERVAL,
    false
)

Jamie Pate가 올바르게 언급했듯이 다이제스트 사이클 내에서 직접 DOM에 액세스하는 것은 그다지 좋은 생각이 아니기 때문에 스코프에 바인딩할 수 있는 다른 타이머 기반 변형을 작성했습니다.

.directive("sizeWatcher", ['$timeout', function ($timeout) {
    return {
        scope: {
            sizeWatcherHeight: '=',
            sizeWatcherWidth: '=',
        },
        link: function( scope, elem, attrs ){
            function checkSize(){
                scope.sizeWatcherHeight = elem.prop('offsetHeight');
                scope.sizeWatcherWidth = elem.prop('clientWidth');
                $timeout( checkSize, 1000 );
            }
            checkSize();
        }
    };
}

이것으로, 임의의 요소에 바인드 할 수 있습니다.

<img size-watcher size-watcher-height="myheight">
<div style="height: {{ myheight }}px">

따라서 div는 항상 이미지와 동일한 높이(지연 1초)를 유지합니다.

이 접근법은 요소의 높이와 폭을 감시하고 요소 속성에 제공된 범위의 변수에 할당합니다.

 <div el-size="size"></div>


.directive('elSize', ['$parse', function($parse) {
  return function(scope, elem, attrs) {
    var fn = $parse(attrs.elSize);

    scope.$watch(function() {
      return { width: elem.width(), height: elem.height() };
    }, function(size) {
      fn.assign(scope, size);
    }, true);

  }
}])

언급URL : https://stackoverflow.com/questions/19048985/angularjs-better-way-to-watch-for-height-change

반응형