AngularJS:更好的观察身高变化的方法

Sch*_*tod 37 html javascript css angularjs

我有旧的可变高度导航问题:position: fixes顶部导航和margin-top: $naviHeight下面的内容.当数据异步加载时导航可以改变高度,因此内容的边距必须随之改变.

我希望这是自成一体的.所以没有加载数据的代码,只有在涉及的html-elements /指令中.

目前我在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();
        }
    }

} ] )
Run Code Online (Sandbox Code Playgroud)

这有一个明显的缺点,使用计时器(我觉得有点难看)和导航调整大小后的一定延迟,直到内容被移动.

有一个更好的方法吗?

Alw*_*ner 40

这通过注册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();
            } );
        }
    }

} )
Run Code Online (Sandbox Code Playgroud)

  • @Scheintod为什么不检查某些事件的高度变化:何时加载异步数据或用户点击某处而不是固定间隔? (3认同)
  • 谁改变了__高度?我认为这不会起作用,因为有些代码应该更新这个变量. (2认同)

Dor*_*hen 24

您可以在不使用Div的情况下监视元素的高度变化,只需编写一个$watch语句:

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

  • linkElement [0] .offsetHeight适合我,.height()不行 (4认同)
  • 调用`height()`可能会导致`reflow`,这对性能来说很糟糕.`AngularJS`旨在避免在摘要周期中访问任何`DOM`,并且您违反了这一原则.计时器是优选的. (4认同)

Che*_*niv 13

可能你应该注意$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...

           })
        }
    }    
} ] )
Run Code Online (Sandbox Code Playgroud)


Ada*_*amy 6

我使用了$ watch和resize事件的组合.我发现没有范围.$ apply(); 在resize事件中,元素的高度变化并不总是被$ 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();
        });
    };
Run Code Online (Sandbox Code Playgroud)