Angular2、ZoneJS 和外部更改 DOM

Angular2, ZoneJS and externally changed DOM

我需要一些关于 Angular2 RC1 网络应用程序中外部更改 DOM 的帮助。场景很简单:我确实有一个带有相应模板的组件,该模板包含一个空的 div 和一个像这样的 ID

<div id="my-svg-canvas"></div>

打字稿组件有一个 ngOnInit 方法,它从一个普通的 JS 文件触发一个函数,该文件通过脚本标签包含在 index.html 中。该函数将 SVG 呈现到上面列出的 "div" 标记中。 SVG 包含一些带有单击指令的 a 元素,这些指令引用了我的组件中的多个方法。

在 SVG 完全写入后调用 $scope.$apply() 之后,在 Angular1 中工作正常。现在,在 Angular2 中,我的组件中的相应方法未被触发。

我知道,ZoneJS 现在负责检测 DOM 中的变化。我希望这是对在 Angular 托管组件内呈现的整个 DOM 自动完成的。接下来的尝试是在我的组件中注入 NgZone 并在其中显式 运行 渲染函数,如下所示:

ngOnInit() {
  this.ngZone.run(() => {renderSVG(this.myData, "my-svg-canvas");})
}

也没有成功:-/ 此外,我注册了一个 MutationObserver(请参阅此线程:),因为出现的问题与我有点相似。不过,它也没有开火。

我不知道去哪里找,也没有错误信息可以参考:-???

注意:必须使用 "on-click" 而不是“(click)”,因为 SVG 渲染框架拒绝设置无效属性。显然,以括号开头的属性适用于 HTML,但不适用于 XML。然而,这应该不是问题,因为这两个指令是完全可以互换的。

PS:

调用的呈现方法使用 SVG.js 框架,如下所示:

function renderSVG(dataParam, elementIdParam) {
  draw = SVG(elementIdParam).spof();
  initAndPaint(draw, dataParam);
  return draw; 
 }

以及由 SVG.js lib

生成的标签
<a id="SvgjsA1033" on-click="showVal('W1')" class="union">

当我将生成的 SVG 代码粘贴到我的模板中时,一切正常。

我会将您的代码移动到组件的 ngAfterViewInit 挂钩方法中:

ngAfterViewInit() {
  this.ngZone.run(() => {renderSVG(this.myData, "my-svg-canvas");})
}

此外,您应该使用 ViewChild 装饰器引用您的 DOM 元素:

<div #mySvgCanvas"></div>

@ViewChild('mySvgCanvas')
mySvgCanvasElt: ElementRef;

ngAfterViewInit() {
  var elt = this.mySvgCanvasElt.nativeElement;

我认为这里不需要明确使用区域...

我认为 Angular 不会解析您动态添加的 HTML(请参阅 )。

因此,在调用 renderSVG() 之后,您可能需要遍历 DOM 并找到新添加的 a 元素,然后手动添加(然后删除)一个每个事件处理程序。

参见

有关更复杂的方法,请参阅

Mark Rajcok 的 link(参见 "For a more involved approach")在已接受的答案中使用 DynamicLoaderComponent 的解决方案有效。作为该线程的闭包,这是我的实现:

constructor(private loader: DynamicComponentLoader, private injector:Injector) {}

ngAfterViewInit() {
  let tournamentCanvas = document.createElement("canvas");
  renderKOTournamentSVG(this.tournament, tournamentCanvas);

  @Component({
    selector: 'canvas-component',
    template: tournamentCanvas.outerHTML)}
  class CanvasComponent {}

  this.loader.loadAsRoot(CanvasComponent, "canvas-component", this.injector);
 }