在 Dom 完成渲染之后,如何运行指令?

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

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

类似的情况也在指令内部发生:

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.

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?

131757 次浏览

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

你可以尝试使用0延迟的 $暂停,比如:

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

它的工作原理:

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

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

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).

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

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

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


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

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


}
}
});

我是这么做的:

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


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


});

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

在所需的外部资源或长时间运行的控制器/指令完成后添加 $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();
}

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

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


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

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

我有以下 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).

有用但很脏:

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

也许对某人有帮助。