Angular 2+应用程序上嵌入的Twitter小部件仅显示在第一页加载

时间:2017-11-08 09:39:19

标签: angular twitter angular-routing twitter-widget

如果我将Twitter文档(https://dev.twitter.com/web/javascript/loading)中的内置函数完全复制到ngAfterViewInit函数中,我的应用程序可以正常工作,但是当我切换路径时,窗口小部件也会消失。

以下是仅适用于第一页加载的代码:

import { Component, OnInit, OnDestroy, AfterViewInit } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute, ParamMap, Params } from '@angular/router';
import { Observable, Subscription } from 'rxjs/Rx';

export class ProjectDetailComponent implements OnInit, OnDestroy, AfterViewInit {

constructor(
    private route: ActivatedRoute,
    private router: Router
  ) { }

ngOnInit(){}

ngAfterViewInit(){
  (<any>window).twttr = (function(d, s, id) {
      let js, fjs = d.getElementsByTagName(s)[0],
        t = (<any>window).twttr || {};
      if (d.getElementById(id)) return t;
      js = d.createElement(s);
      js.id = id;
      js.src = 'https://platform.twitter.com/widgets.js';
      fjs.parentNode.insertBefore(js, fjs);

      t._e = [];
      t.ready = function(f) {
        t._e.push(f);
      };

      return t;
    }(document, 'script', 'twitter-wjs'));
}

}

然后我找到了一个可接受的解决方案(Twitter widget on Angular 2),但是小部件甚至没有从第一次加载显示,也没有错误,所以我甚至不知道我错在哪里。

这是从未显示Twitter小部件而没有任何错误的代码:

import { Component, OnInit, OnDestroy, AfterViewInit } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute, ParamMap, Params } from '@angular/router';
import { Observable, Subscription } from 'rxjs/Rx';

export class ProjectDetailComponent implements OnInit, OnDestroy, AfterViewInit {

private subscription: Subscription;
constructor(
    private route: ActivatedRoute,
    private router: Router
  ) { }

ngOnInit(){}

ngAfterViewInit(){
  this.subscription = this.router.events.subscribe(val => {
  if (val instanceof NavigationEnd) {
    (<any>window).twttr = (function (d, s, id) {
      let js: any, fjs = d.getElementsByTagName(s)[0],
          t = (<any>window).twttr || {};
      if (d.getElementById(id)) return t;
      js = d.createElement(s);
      js.id = id;
      js.src = 'https://platform.twitter.com/widgets.js';
      fjs.parentNode.insertBefore(js, fjs);

      t._e = [];
      t.ready = function (f: any) {
          t._e.push(f);
      };

      return t;
    }(document, 'script', 'twitter-wjs'));

    if ((<any>window).twttr.ready())
      (<any>window).twttr.widgets.load();
  }
});
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}    
}

基本上,我订阅了小部件数据,直到NavigationEnd然后在ngOnDestroy中取消订阅,所以我仍然可以保留路由切换之间的数据。我相信逻辑是正确的,因为解决方案也适用于某人,但对我来说,它直到现在才开始工作。

3 个答案:

答案 0 :(得分:3)

尝试此操作,无需订阅或超时。

ngOnInit() {
   (<any>window).twttr.widgets.load();
}

答案 1 :(得分:2)

我知道这是一个老问题,但我得到了一个比设置超时更好的解决方案。我在this问题中作为解决方案发布的代码在Angular 4或Angular 5之后就被打破了 - 我不记得了。我也会在那里更新我的答案。

所以,要解决这个问题,只需将代码放在构造函数中(以便窗口小部件在视图之前加载),如下所示:

import { Component, OnDestroy } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({ ... })

export class HomeComponent implements OnDestroy {
  private twitter: any;

  constructor(private _router: Router) {
    this.initTwitterWidget();
  }

  initTwitterWidget() {
    this.twitter = this._router.events.subscribe(val => {
      if (val instanceof NavigationEnd) {
        (<any>window).twttr = (function (d, s, id) {
          let js: any, fjs = d.getElementsByTagName(s)[0],
              t = (<any>window).twttr || {};
          if (d.getElementById(id)) return t;
          js = d.createElement(s);
          js.id = id;
          js.src = "https://platform.twitter.com/widgets.js";
          fjs.parentNode.insertBefore(js, fjs);

          t._e = [];
          t.ready = function (f: any) {
              t._e.push(f);
          };

          return t;
        }(document, "script", "twitter-wjs"));

        if ((<any>window).twttr.ready())
          (<any>window).twttr.widgets.load();

      }
    });
  }

  ngOnDestroy() {
    this.twitter.unsubscribe();
  }
}

如果我发现有关前一代码被破坏的原因的任何信息,我将更新此答案。 (或者,如果有其他人知道,请随时编辑此内容)

答案 2 :(得分:0)

好的,我找到了一种基于此参考(Why will my twitter widget not render if i change the view in angularjs?)的解决方法。不需要事件订阅,我需要将函数包装到setTimeOut以在路由切换之间重新呈现它。请记住将setTimeOut函数包装在isPlatformBrowser中,以便更好地预渲染。这是代码:

import { Component, OnInit, OnDestroy, AfterViewInit, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

constructor(@Inject(PLATFORM_ID) private platformId: Object) { }

ngAfterViewInit() {    
 if (isPlatformBrowser(this.platformId)) {
  setTimeout(function() { 
    (<any>window).twttr = (function(d, s, id) {
      let js, fjs = d.getElementsByTagName(s)[0],
        t = (<any>window).twttr || {};
      if (d.getElementById(id)) return t;
      js = d.createElement(s);
      js.id = id;
      js.src = 'https://platform.twitter.com/widgets.js';
      fjs.parentNode.insertBefore(js, fjs);

      t._e = [];
      t.ready = function(f) {
        t._e.push(f);
      };

      return t;
    }(document, 'script', 'twitter-wjs'));
    (<any>window).twttr.widgets.load(); }, 100);
  }
}