问题描述
假设,我正在制作一个自定义Angular指令,该指令必须检查和操作其中的DOM树(准确地说:该指令所应用的元素下的DOM树).此类操作的正确位置是指令的后链接功能.
Suppose, I am making a custom Angular directive that has to examine and manipulate the DOM tree inside it (to be precise: the DOM tree under the element the directive is applied to). The right place for such manipulation is the directive's post-link function.
当内联指令中的所有HTML时,这都可以正常工作.在指令内部,当我们有其他指令使用"templateUrl"属性或仅使用"ng-include"指令来插入部分内容时,就会出现问题.
That works fine while all the HTML inside the directive is inlined. Problems appear when inside the directive we have other directives that load their templates using "templateUrl" property, or just "ng-include" directives to insert partials.
那些模板和局部文件是异步加载的.这意味着,在编译阶段,Angular将启动部分加载并继续编译,而无需等待加载完成.然后,在链接父指令时,所包含的部分加载可能仍在进行中,因此该指令的post-link函数内部看不到任何内容.
Those templates and partials are loaded asynchronously. That means, at the compile stage Angular will initiate the partial loading and will continue compiling without waiting for the loading to complete. Then, at the moment the parent directive is linked, the contained partials loading may still be in progress, so the directive's post-link function sees nothing inside.
换句话说:伪指令的后链接功能旨在在调用它之前准备好所有嵌套的DOM,但是使用异步模板并包括这种情况!
In other words: the directive's post-link function is designed to have all nested DOM ready by the moment it is called, but with the async templates and includes this is not the case!
模板预加载无济于事,因为它们仍然可以异步访问.
And template pre-loading does not help, because they are still accessed asynchronously.
人们如何克服呢?
任务似乎很普通,但是我没有设法找到一个好的且可靠的解决方案.我想念一些明显的东西吗?...
The task seems to be quite common, but I did not manage to find a good and reliable solution. Do I miss something obvious?...
更新:我已经创建了一个 Plunk 来说明问题.实际上,它仅重现了ng-include
的问题,这是子指令工作的外部模板.在我的项目中并没有,也许这是一个竞赛条件,我必须进行更多调查.
Update: Well I have created a Plunk to illustrate the problem. Actually it reproduces only the problem with ng-include
, the external template for sub-directive works. In my project it did not though, maybe this is a race condition, I have to investigate more.
推荐答案
您可以使用以下方法等待主视图的加载:
You can wait for the load of the main view with:
$scope.$on('$viewContentLoaded', function () {
//Here your view content is fully loaded !!
});
如果您正在加载带有ng-include的视图,则该技巧与$timeout
相同,将不起作用.您应该等待所有局部视图.正确的事件顺序是:
This trick, same as $timeout
, not works if you are loading views with ng-include. You should wait for all the partial views. The right events order is:
- $ viewContentLoaded
- $ includeContentRequested
- $ timeout
- $ includeContentLoaded
您可以将$includeContentRequested
和$includeContentLoaded
与计数器一起使用,以等待全部包含的部分内容的内容:
You can use $includeContentRequested
and $includeContentLoaded
with a counter for wait the content of all included partials:
var nIncludes = 0;
$scope.$on('$includeContentRequested', function (event, templateName) {
nIncludes++;
console.log(nIncludes, '$includeContentRequested', templateName);
});
$scope.$on("$includeContentLoaded", function (event, templateName) {
nIncludes--;
console.log(nIncludes, '$includeContentLoaded', templateName);
if (nIncludes === 0) {
console.log('everything is loaded!!');
// Do stuff here
}
});
我还没有找到其他更优雅的解决方案.
I have not found another more elegant solution.
这篇关于Angular指令:如何确保所有嵌套的模板和局部文件都已加载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!