渲染后从组件获取 innerHTML

Get innerHTML from component AFTER render

我正试图从 DOM 中“窃取”由自己的组件生成的 SVG 代码。我是这样做的:

<my-own-component id="my-component-id" #myComponentId
                        [data]="data"></my-own-component>
onButtonClick() {
   this.data = someData;
   const svgCode = document.getElementById('my-component-id').innerHTML;
}

也试过(还是不行):

@ViewChild('myComponentId') myComponentId;
...
onButtonClick() {
   this.data = someData;
   const svgCode = this.myComponentId.nativeElement.children[0].innerHTML;
}

问题是我得到的内容before Angular已经应用了由this.data = someData引起的变化,所以不包括SVG的元素. 我已经“解决”了引入 50 毫秒超时的问题。这可行,但不是正确的解决方案,是一个错误的补丁:

this.data = someData;        
await new Promise(resolve => setTimeout(resolve.bind(null, null), 50));
const svgCode = document.getElementById('my-component-id').innerHTML;

我希望能够等待 Angular 完成组件渲染。有什么办法吗?

提前致谢。

尝试 AfterViewInit 生命周期钩子。是这样实现的

export class MyComponent implements AfterViewInit {
  ngAfterViewInit() {
    // code that should be executed after view initialization
  }
}

您只需要使用 class 添加 AfterViewInit 生命周期挂钩。我还建议您在 OnInit 生命周期内分配 属性 。您的父组件应如下所示

export class appComponent implements OnInit, AfterViewInit{

 ngOnInit(): void {
  this.data = someData;
 }
 ngAfterViewInit(): void{
  const svgCode = document.getElementById('my-component-id').innerHTML;
 }

}

Elezan,问题是你需要“让 Angular 喘口气”。如果你有,例如

<div>{{data}}</div>
click(){
  this.data="......."
  //here you don't can check the value of innerHtml
}

这个“呼吸”使用了 setTimeout

<div>{{data}}</div>
click(){
  this.data="......."
  setTimeout(()=>{
     //now here you can check the value of innerHtml
  })
}

认为Angular,当你调用点击功能时,执行所有指令并“重绘”应用程序。因此,在第一种情况下,您试图在 Angular“重绘”之前获取 innerHTML。使用 setTimeout 你对 Angular 说:“嘿!你重画,然后,不要忘记进入 setTimeout 的指令” - 看到 setTimeout 没有毫秒 -

另一种方法是在构造函数中注入 ChangeDetectorRef 并在尝试获取 innerHTML

之前使用 markForCheck()

更新 另一个使用 observables 的例子

$observable.subscribe(res=>{
    this.data=res
    setTimeout(()=>{
         ..get the innerHTML
    })
})

或承诺

$promise.then(
  res=>{
    this.data=res
    setTimeout(()=>{
         ..get the innerHTML
    }),
  err=>{...}
)

await:

const svgCode = await new Promise<string>(resolve => { 
    setTimeout(() => {
        resolve(document.getElementById('my-component-id').innerHTML));
    });  
});