加载模板 dom 时,angular2 模板/钩子中的脚本标记

IT技术 javascript jquery angular
2021-01-19 02:57:57

我很困,不知道如何解决我的问题......

简化:我有一个基于绑定创建 ulist 的组件,如下所示:

@Component({
   selector: "template",
   template: `
     <ul>
       <li *ng-for="#challenge of jobs.challenges">{{challenge}}</li>
     </ul>
   `})
export class JobTemplate{
  jobs: Jobs;
  constructor(jobs:Jobs){
    this.jobs = jobs
  }     
}

组件选择器/主机嵌入在由 php 回显的普通 html 流中,用于替换预定义的 ulist。问题在于,在普通站点上,使用 ulist 后的脚本标记对列表应用了一些 jquery 魔法。

由于脚本标记在我的组件模板加载完成之前被回显,因此 jquery 调用将找不到我的模板 DOM 的元素。将脚本标签放在我的模板中(最后)不起作用;它似乎只是被忽略了。

<ul>
  <a><li *ng-for="#challenge of jobs.challenges">{{challenge}}</li></a>  
</ul>
<script>
   $("ul a").on("click", function (event)
        {
        var parent = $(this).parent();
        if(parent.hasClass('active'))
          ....slideToggle("normal");
        else
        ....
        });
</script>

该站点还使用基础框架,每次将新元素添加到页面时(例如,通过外部更新我的组件的绑定),我都需要调用$(document).foundation().

所以我的问题是,当我不知道我的模板是否已完成创建时,如何实现在我的模板 DOM 上调用 jquery。在我的组件模板中定义时,onload 处理程序也不起作用。

我已经阅读了 AfterViewInit,但我对它有点不知所措。有人可以把我推向正确的方向吗?

我怎样才能知道我的组件的模板何时已经完全插入到“主”DOM 中?

2个回答

组件模板中的脚本标签被删除。一种解决方法是在ngAfterViewInit()

另见https://github.com/angular/angular/issues/4903

constructor(private elementRef:ElementRef) {};

ngAfterViewInit() {
  var s = document.createElement("script");
  s.type = "text/javascript";
  s.src = "http://somedomain.com/somescript";
  this.elementRef.nativeElement.appendChild(s);
}

另见https://stackoverflow.com/a/9413803/217408

更好的方法可能是仅用于require()加载脚本。

另请参阅加载模板 dom 时 angular2 模板/钩子中的脚本标记

当然,最好根本不要使用外部脚本:)
2021-03-31 02:57:57
感谢那。当我发布时,我刚开始使用 angular,我完全使用了错误的方法。这只是将点击处理程序添加到模板元素,当然,在这种情况下,使用 angular2 的模板语法更舒服<elem #a (click)="doSth(a)"></elem>
2021-04-02 02:57:57

我遇到了同样的问题,但另外我必须加载一些脚本,其中一些可以并行加载,而另一些可以串行加载。如果您使用的是TypeScript 2.1 或更高版本此解决方案将起作用,它具有对async/await 的本机支持并转换为 ES3/ES5:

async ngAfterViewInit() {
  await this.loadScript("http://sub.domain.tld/first-script.js")
  await this.loadScript("http://sub.domain.tld/second-script.js")
}

private loadScript(scriptUrl: string) {
  return new Promise((resolve, reject) => {
    const scriptElement = document.createElement('script')
    scriptElement.src = scriptUrl
    scriptElement.onload = resolve
    document.body.appendChild(scriptElement)
  })
}

对于任何可以并行加载的脚本,您都可以利用Promise.all

async ngAfterViewInit() {
  await Promise.all([
    this.loadScript("http://sub.domain.tld/first-parallel.js"),
    this.loadScript("http://sub.domain.tld/second-parallel.js")
  ])
  await this.loadScript("http://sub.domain.tld/after-parallel.js")
}

注意:对于Promise拒绝,您可以尝试scriptElement.onerror = rejectloadScript()函数中使用,但是,我在这种情况下遇到了一些古怪的行为。如果您希望脚本无论如何都继续加载,您可能需要尝试在调用 onerror 时解析 promise。