dom完成渲染后如何运行指令?

时间:2012-09-02 23:43:22

标签: jquery dom callback angularjs document-ready

我有一个看似简单的问题,没有明显的(通过阅读Angular JS文档)解决方案。

我有一个Angular JS指令,它根据其他DOM元素的高度进行一些计算,以定义DOM中容器的高度。

在指令内部会发生类似的事情:

return function(scope, element, attrs) {
    $('.main').height( $('.site-header').height() -  $('.site-footer').height() );
}

问题是当指令运行时,找不到$('site-header'),返回一个空数组而不是我需要的jQuery包装DOM元素。

我是否可以在我的指令中使用回调,只在DOM加载后才能运行,我可以通过正常的jQuery选择器样式查询访问其他DOM元素?

6 个答案:

答案 0 :(得分:136)

这取决于你的$('site-header')是如何构建的。

您可以尝试使用$timeout 0延迟。类似的东西:

return function(scope, element, attrs) {
    $timeout(function(){
        $('.main').height( $('.site-header').height() -  $('.site-footer').height() );
    });        
}

说明工作原理:onetwo

不要忘记在你的指令中注入$timeout

.directive('sticky', function($timeout)

答案 1 :(得分:43)

我是这样做的:

app.directive('example', function() {

    return function(scope, element, attrs) {
        angular.element(document).ready(function() {
                //MANIPULATE THE DOM
        });
    };

});

答案 2 :(得分:37)

可能作者不再需要我的回答了。尽管如此,为了完整起见,我觉得其他用户可能会发现它很有用。最好和最简单的解决方案是在返回函数的主体内部使用$(window).load()。 (或者您可以使用document.ready。这实际上取决于您是否需要所有图像。)

在我的拙见中使用$timeout是一个非常弱的选择,在某些情况下可能会失败。

以下是我使用的完整代码:

.directive('directiveExample', function(){
   return {
       restrict: 'A',
       link: function($scope, $elem, attrs){

           $(window).load(function() {
               //...JS here...
           });
       }
   }
});

答案 3 :(得分:8)

有一个ngcontentloaded事件,我想你可以使用它

.directive('directiveExample', function(){
   return {
       restrict: 'A',
       link: function(scope, elem, attrs){

                $$window = $ $window


                init = function(){
                    contentHeight = elem.outerHeight()
                    //do the things
                }

                $$window.on('ngcontentloaded',init)

       }
   }
});

答案 4 :(得分:5)

如果由于外部资源而无法使用$ timeout,并且由于时间的特定问题而无法使用指令,请使用广播。

在所需的外部资源或长时间运行的控制器/指令完成后添加$scope.$broadcast("variable_name_here");

然后在加载外部资源后添加以下内容。

$scope.$on("variable_name_here", function(){ 
   // DOM manipulation here
   jQuery('selector').height(); 
}

例如,在延迟HTTP请求的承诺中。

MyHttpService.then(function(data){
   $scope.MyHttpReturnedImage = data.image;
   $scope.$broadcast("imageLoaded");
});

$scope.$on("imageLoaded", function(){ 
   jQuery('img').height(80).width(80); 
}

答案 5 :(得分:1)

我遇到了类似的问题,想在这里分享我的解决方案。

我有以下HTML:

<div data-my-directive>
  <div id='sub' ng-include='includedFile.htm'></div>
</div>

问题:在父div的指令的link-function中,我想要jquery“div div”sub。但是它只是给了我一个空对象,因为当指令的链接功能运行时,ng-include还没有完成。所以首先我用$ timeout做了一个脏的解决方法,但是延迟参数取决于客户端的速度(没有人喜欢)。

工作但很脏:

app.directive('myDirective', [function () {
    var directive = {};
    directive.link = function (scope, element, attrs) {
        $timeout(function() {
            //very dirty cause of client-depending varying delay time 
            $('#sub').css(/*whatever*/);
        }, 350);
    };
    return directive;
}]);

这是一个干净的解决方案:

app.directive('myDirective', [function () {
    var directive = {};
    directive.link = function (scope, element, attrs) {
        scope.$on('$includeContentLoaded', function() {
            //just happens in the moment when ng-included finished
            $('#sub').css(/*whatever*/);
        };
    };
    return directive;
}]);

也许对某人有帮助。