【问题标题】:How to run a jquery function in Angular 2 after every component finish loading在每个组件完成加载后如何在 Angular 2 中运行 jquery 函数
【发布时间】:2016-06-14 05:08:56
【问题描述】:

我已经尝试了所有生命周期钩子,但无法完成所需的结果。 我需要的结果是触发一个函数,该函数在加载每个元素(组件)后初始化用于单个页面上不同元素的许多 jquery 插件。

假设你有这个结构。

主页 滑块 小部件 产品旋转器 ..等等

这些元素中的每一个都有自己的组件,并且都是主页父组件的子组件。

这里我需要知道所有子组件和父组件何时加载,因此我触发了一个 jquery 函数来初始化页面上的每个插件。

【问题讨论】:

  • 你找到解决这个问题的办法了吗?

标签: jquery components angular onload document-ready


【解决方案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.onStablezone.onMicrotaskEmpty

    ngAfterViewInit() {
      this.zone.onStable.first().subscribe(() => {
        debugger;
      });
    }
    

    ngOnInit() {
      this.service.getData().subscribe(() => {
        this.data = data;
        this.zone.onMicrotaskEmpty.first().subscribe((data) => {
          $(someElem).plugin();
        });
      });
    }
    

    另见

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 2017-08-01
      • 1970-01-01
      相关资源
      最近更新 更多