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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12240639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 11:28:12  来源:igfitidea点击:

How can I run a directive after the dom has finished rendering?

jquerydomcallbackangularjsdocument-ready

提问by Jannis

I've got a seemingly simple problem with no apparent (by reading the Angular JS docs)solution.

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

I have got an Angular JS directive that does some calculations based on other DOM elements' height to define the height of a container in the DOM.

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

Something similar to this is going on inside the directive:

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

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

The issue is that when the directive runs, $('site-header')cannot be found, returning an empty array instead of the jQuery wrapped DOM element I need.

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

Is there a callback that I can use within my directive that only runs after the DOM has been loaded and I can access other DOM elements via the normal jQuery selector style queries?

是否有我可以在我的指令中使用的回调,该回调仅在 DOM 加载后运行,并且我可以通过普通的 jQuery 选择器样式查询访问其他 DOM 元素?

回答by Artem Andreev

It depends on how your $('site-header') is constructed.

这取决于您的 $('site-header') 的构造方式。

You can try to use $timeoutwith 0 delay. Something like:

您可以尝试使用$timeout和 0 延迟。就像是:

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

Explanations how it works: one, two.

解释它是如何工作的:

Don't forget to inject $timeoutin your directive:

不要忘记注入$timeout您的指令:

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

回答by rjm226

Here is how I do it:

这是我如何做到的:

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

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

});

回答by jnardiello

Probably the author won't need my answer anymore. Still, for sake of completeness i feel other users might find it useful. The best and most simple solution is to use $(window).load()inside the body of the returned function. (alternatively you can use document.ready. It really depends if you need all the images or not).

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

Using $timeoutin my humble opinion is a very weak option and may fail in some cases.

使用$timeout在我的愚见是一个非常薄弱的选项,并在某些情况下可能会失败。

Here is the complete code i'd use:

这是我将使用的完整代码:

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

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

回答by sunderls

there is a ngcontentloadedevent, I think you can use it

有一个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)

       }
   }
});

回答by JSV

If you can't use $timeout due to external resources and cant use a directive due to a specific issue with timing, use broadcast.

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

Add $scope.$broadcast("variable_name_here");after the desired external resource or long running controller/directive has completed.

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

Then add the below after your external resource has loaded.

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

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

For example in the promise of a deferred HTTP request.

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

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

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

回答by jaheraho

I had the a similar problem and want to share my solution here.

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

I have the following HTML:

我有以下 HTML:

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

Problem: In the link-function of directive of the parent div I wanted to jquery'ing the child div#sub. But it just gave me an empty object because ng-include hadn't finished when link function of directive ran. So first I made a dirty workaround with $timeout, which worked but the delay-parameter depended on client speed (nobody likes that).

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

Works but dirty:

有效但很脏:

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;
}]);

Here's the clean solution:

这是干净的解决方案:

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;
}]);

Maybe it helps somebody.

也许它可以帮助某人。