简体   繁体   English

在 Angular 加载完所有视图后运行 Javascript

[英]Run Javascript AFTER Angular Has Finished Loading All Views

I am building a web application using Angular, and I am trying to find a way to wait until all of the data-ng-include elements have been evaluated and the includes finished loading.我正在使用 Angular 构建一个 Web 应用程序,我试图找到一种方法来等待所有data-ng-include元素都已评估并且包含完成加载。 For instance the menu is a view that is loaded, as is the main content for each page, so at the very least there are two data-ng-include s that get evaluated and loaded.例如,菜单是一个加载的视图,每个页面的主要内容也是如此,因此至少有两个data-ng-include被评估和加载。 On top of that the menu include has nested data-ng-repeat s that build out my menu.最重要的是,菜单 include 嵌套了data-ng-repeat来构建我的菜单。 I need a way to initiate script AFTER all of these includes and any angular functions inside them have been loaded and the DOM is ACTUALLY ready.我需要一种在所有这些包含和其中的任何角度函数都已加载并且 DOM 实际准备就绪后启动脚本的方法。

Is there any event that gets fired when Angular has finished setting up the page?当 Angular 完成页面设置时,是否有任何事件被触发?

The implementation of AnguarJS is basic and we are basically using it for templating via use of data-ng-include. AnguarJS 的实现是基本的,我们基本上通过使用 data-ng-include 将其用于模板化。 Each page is a view (not an angular view, just an html file), loaded via data-ng-include, with the header and footer above and below it.每个页面都是一个视图(不是角度视图,只是一个 html 文件),通过 data-ng-include 加载,页眉和页脚在其上方和下方。 The header also dynamically loads a global view (again not an angular view) html file that includes angular.标头还动态加载包含 angular.html 的全局视图(同样不是角度视图)html 文件。

So far the menu is the only thing using AngularJS for anything other than templating.到目前为止,除了模板之外,菜单是唯一使用 AngularJS 的东西。 It uses it to create a menu using a JSON object that is dynamically generated by JSP and inserted into the DOM that is returned from the server.它使用它使用 JSP 动态生成并插入到从服务器返回的 DOM 中的 JSON 对象来创建菜单。

In order to make life easier for the front-end guys, any kind of repeated JavaScript functionality is coded out into modules, which are detected on page load and loaded dynamically using a data-features attribute on the element the JavaScript functionality needs to be attached to.为了让前端人员的工作更轻松,任何类型的重复 JavaScript 功能都被编码到模块中,这些模块在页面加载时被检测到,并使用需要附加 JavaScript 功能的元素上的 data-features 属性动态加载到。

For instance, you may have <div id="mySubMenu" data-features="subMenu"></div> .例如,您可能有<div id="mySubMenu" data-features="subMenu"></div> On page load, each element with a data-features element is detected, and the associated JS module loaded, in this case we would load /scripts/modules/subMenu.js .在页面加载时,会检测每个带有 data-features 元素的元素,并加载关联的 JS 模块,在这种情况下,我们将加载/scripts/modules/subMenu.js

What I need is a way to delay running this feature detection and attachment until all of the elements resulting from an include or other angular function are on the page and ready to be manipulated, especially since there may be elements with data-features attributes inside those includes.我需要的是一种延迟运行此功能检测和附件的方法,直到包含或其他角度函数产生的所有元素都在页面上并准备好进行操作,特别是因为其中可能存在具有数据特征属性的元素包括。

Someone elsewhere had mentioned putting a controller on the body and putting nothing side of it but:其他地方有人提到在身体上放一个控制器,但什么都不放:

$scope.$on('$viewContentLoaded', function() {
    // Init Features Here
});

That did not work, so I am here looking for other options.那没有用,所以我在这里寻找其他选择。

I ended up going with Theo's solution in this question: Sending event when angular.js finished loading我最终在这个问题中使用了 Theo 的解决方案: 当 angular.js 完成加载时发送事件

on content loaded:在加载的内容上:

$rootScope.$on('$includeContentLoaded', function() {
    //do your will
});

on content requested:关于请求的内容:

$rootScope.$on('$includeContentRequested', function() {
    //...
});

I am certain that this is not the correct way to do it but....我确信这不是正确的方法,但是......

Putting the below function in my view controller, ran the function after the view had loaded in my application.将下面的函数放在我的视图控制器中,在视图加载到我的应用程序中后运行该函数。 I believe that the function is run in the next digest cycle following the view load (correct me here if wrong), so it is run once the page is formed.我相信该函数会在视图加载后的下一个摘要循环中运行(如果错误,请在此处纠正我),因此它会在页面形成后运行。

setTimeout(function(){
  //do this after view has loaded :)
  console.log('success!');
}, 0);

Its possible you could chain these together via callbacks and/or use an async parallel library to execute another function, after each of the views setTimeouts had returned.在每个视图 setTimeouts 返回后,您可以通过回调将它们链接在一起和/或使用异步并行库来执行另一个函数。

I think the appropiate answer is NO.我认为合适的答案是否定的。 You have to change the way you are looking at your app and Model and adapt it to the "angular way".您必须改变查看应用程序和模型的方式,并使其适应“角度方式”。 Most likely there is a healthier way to achieve what you need.很可能有一种更健康的方式来实现您的需求。 If you need to attach events to elements probably you may want to use a directive but of course I do not have enough information to judge at this stage what is best.如果您需要将事件附加到元素,您可能想要使用指令,但当然我没有足够的信息在这个阶段判断什么是最好的。

angular.module along with directives is a good option to explore. angular.module 和指令是一个很好的探索选择。

Here is a plunker demo on how to use both with a JQUERY plug in:这是一个关于如何将两者与 JQUERY 插件一起使用的 plunker 演示:

http://plnkr.co/edit/WGdNEM?p=preview http://plnkr.co/edit/WGdNEM?p=preview

Here is a an example with a directive on a separate file:这是一个在单独文件上带有指令的示例:

http://plnkr.co/edit/YNBSWPLeWqsfGvOTwsMB?p=preview http://plnkr.co/edit/YNBSWPLeWqsfGvOTwsMB?p=preview

You can use a JQuery Promise, and fulfill this promise within your angular root controller.您可以使用 JQuery Promise,并在您的 Angular 根控制器中实现此承诺。 Setup the promise before the angular controller or jquery code runs:在 angular 控制器或 jquery 代码运行之前设置承诺:

var AppReadyDeferred = $.Deferred();
var AppReadyPromise = AppReadyDeferred.promise();

Inside your angular controller once everything is ready, do一旦一切准备就绪,在你的角度控制器里面,做

AppReadyDeferred.resolve();

And in your jQuery code wait for it to be resolved在你的 jQuery 代码中等待它被解决

window.AppReadyPromise.done(() => {
  // Angular is ready to go!;
});

Use ng-cloak to delay templates being shown before compilation.使用 ng-cloak 在编译之前延迟显示模板。 You can also add a hidden field as the very last child to your html element that has ng-cloak (better to use it in body tag or wherever your ng-app starts) and then you can check for existence of this hidden element in an interval loop您还可以向具有 ng-cloak 的 html 元素添加一个隐藏字段作为最后一个子元素(最好在 body 标签或 ng-app 开始的任何地方使用它),然后您可以检查此隐藏元素是否存在间隔循环

Your hidden field part would be like this您的隐藏字段部分将是这样的

<div ng-include="'ngtplhidden'"></hidden>
<script type="text/ng-template" id="ngtplhidden">
<span id="elemidToCheckInAnIntervalFunc"></span>
</script>

You can try using document.onreadystatechange您可以尝试使用document.onreadystatechange

document.onreadystatechange = x => {
    console.log('ready!');
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM