在每个组件完成加载后如何在 Angular 2 中运行 jquery 函数
Posted
技术标签:
【中文标题】在每个组件完成加载后如何在 Angular 2 中运行 jquery 函数【英文标题】:How to run a jquery function in Angular 2 after every component finish loading 【发布时间】:2016-06-14 05:08:56 【问题描述】:我已经尝试了所有生命周期钩子,但无法完成所需的结果。 我需要的结果是触发一个函数,该函数在加载每个元素(组件)后初始化用于单个页面上不同元素的许多 jquery 插件。
假设你有这个结构。
主页 滑块 小部件 产品旋转器 ..等等
这些元素中的每一个都有自己的组件,并且都是主页父组件的子组件。
这里我需要知道所有子组件和父组件何时加载,因此我触发了一个 jquery 函数来初始化页面上的每个插件。
【问题讨论】:
你找到解决这个问题的办法了吗? 【参考方案1】:您将希望通过导入 AfterViewInit (https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#afterview) 来使用“ngAfterViewInit”生命周期挂钩。可以如下图使用:
安装:
tsd install jquery --save
或
typings install dt~jquery --global --save
利用:
import Component, AfterViewInit from '@angular/core';
import * as $ from 'jquery';
ngAfterViewInit()
this.doJqueryLoad();
this.doClassicLoad();
$(this.el.nativeElement)
.chosen()
.on('change', (e, args) =>
this.selectedValue = args.selected;
);
doClassicLoad()
// A $( document ).ready() block.
$( document ).ready(function()
console.log( "Unnecessary..." );
);
// You don't need to use document.ready...
doJqueryLoad()
console.log("Can use jquery without doing document.ready")
var testDivCount = $('#testDiv').length;
console.log("TestDivCount: ", testDivCount);
这是一个例子: http://plnkr.co/edit/KweZYO9hk9Dz8pqDK77F?p=info
【讨论】:
错误:Cannot find name '$'
Angular 2 Final
看来您现在必须声明美元符号。
我在使用 ngAfterViewInit 和 jquery 时遇到问题,因为当我尝试定位元素时它们不存在:ngAfterViewInit() console.log($('#startDateTimeFilter, #endDateTimeFilter).length ); 显示 0 而不是 2。
您的代码中是否有一个尾随撇号,这里缺少一个撇号。我创建了一个获取 div 长度并返回 1 的 plunker。请参见此处:plnkr.co/edit/KweZYO9hk9Dz8pqDK77F
如果你有依赖于 Jquery 的依赖,你应该把 "scripts": [ "node_modules/jquery/dist/jquery.js",
放到你的 angular.json
文件中以获得 angular 6+【参考方案2】:
我发现最有效的方法是在页面/组件构造函数中使用时间为 0 的 setTimeout。这让 jQuery 在 Angular 加载完所有子组件后的下一个执行周期中运行。
export class HomePage
constructor()
setTimeout(() =>
// run jQuery stuff here
, 0);
将 setTimeout 放在 ngOnInit 方法中也对我有用。
export class HomePage
ngOnInit()
setTimeout(() =>
// run jQuery stuff here
, 0);
【讨论】:
这对我有用,但感觉很hacky!是否有关于“正确”方法的更新? Timeout = 0 对我不起作用,但 timeout = 1 起作用。 我使用的不是 JQuery,而是 document.querySelector()。在我遇到这个之前,我已经旋转了几个小时。谢谢! 感谢您的提示。它对我有用...看来我们应该能够在没有这种 hack 的情况下在“AfterViewInit”函数中访问 dom。【参考方案3】:怎么样
bootstrap(...).then(x =>
...
)
否则我会假设你的根组件的ngAfterViewInit()
是一个符合你要求的生命周期钩子,但你说你已经测试了所有......
更新
根组件上的bootstrap()
或ngAfterViewInit()
只能用于初始加载。对于以后添加的组件,可以使用添加的组件的ngAfterViewInit()
。
【讨论】:
我试过了,但是这些事件在页面上没有任何内容之前触发,例如我试图触发他们两个的警报,我得到了这个结果。 postimg.org/image/8qv5tqei9 如您所见,页面上还没有任何内容。我想在页面上的所有内容完全加载后初始化 jquery 插件。生活的钩子似乎都不起作用。 我还没有检查 bootstrap.then 但对于 ngAfterViewInit 来说这不是真的 对我也不起作用。既不是 bootstrap(...).then() 想法,也不是根组件的 ngAfterViewInit() 钩子。对我有用的是在每条路由的每个叶子组件的 ngAfterViewInit 中添加 jquery 插件初始化。【参考方案4】:我在这里遇到了同样的问题。我找到了 2 个解决方案,即使它们不是最好的:
1 - 实现 afterViewChecked 以检查 jquery 插件是否已启动,然后使用变量来控制其初始化。这是困难的方式,因为 afterViewChecked 被调用了很多次。
2 - 我使用 hidden 属性而不是 ngIf 将一些元素更改为隐藏。使用 hidden 我可以使用 afterViewInit 初始化所有 jquery 插件,即使我的对象被隐藏,它们也可以工作。
使用 ngIf 时 setTimeout 不起作用。它在重新渲染内容之前触发。
【讨论】:
【参考方案5】:一种可能的解决方案是订阅zone.onStable
或zone.onMicrotaskEmpty
ngAfterViewInit()
this.zone.onStable.first().subscribe(() =>
debugger;
);
或
ngOnInit()
this.service.getData().subscribe(() =>
this.data = data;
this.zone.onMicrotaskEmpty.first().subscribe((data) =>
$(someElem).plugin();
);
);
另见
Angular 2 calling jQuery after rendering elements - after consuming API【讨论】:
以上是关于在每个组件完成加载后如何在 Angular 2 中运行 jquery 函数的主要内容,如果未能解决你的问题,请参考以下文章