【问题标题】:Get innerHTML from component AFTER render渲染后从组件获取innerHTML
【发布时间】:2021-07-11 07:56:03
【问题描述】:

我试图从 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;
}

问题是我得到内容之前 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 是否也为时过早?也许其中一个离子生命周期钩子可能对您有用:ionicframework.com/docs/angular/lifecycle
  • 什么意思? my-own-component.ngAfterViewInit 还是 my-page.ngAfterViewInit?我试过my-page的,没有成功。

标签: javascript angular typescript ionic-framework capacitor


【解决方案1】:

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

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

【讨论】:

  • 看起来是个好主意。如何从父亲内部等待它?
【解决方案2】:

你只需要在类中添加 AfterViewInit 生命周期钩子。我还建议您在 OnInit 生命周期内分配该属性。你的父组件应该是这样的

export class appComponent implements OnInit, AfterViewInit{

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

}

【讨论】:

  • 不幸的是不是那么容易。 this.data = someData 发生在用户单击按钮时,然后是 my-own-component 更新“太慢”时。我会更新原来的问题。
  • 嗯,对不起,我错过了这一点。然后你可以在你的子组件中附加一个输出事件。一旦你的孩子被渲染,你可以发出输出事件,然后在你的父组件中捕获它,你可以在其中获取 innerhtml。
【解决方案3】:

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,当您调用 click 函数时,会执行所有指令并“重新绘制”应用程序。因此,在第一种情况下,您试图在 Angular“重绘”之前获取 innerHTML。使用 setTimeout 您对 Angular 说:“嘿!您重新绘制,然后不要忘记 setTimeout 的说明” - 看到 setTimeout 没有毫秒 -

另一种方法是注入构造函数ChangeDetectorRef 并在尝试获取innerHTML 之前使用markForCheck()

更新另一个使用可观察对象的例子

$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));
    });  
}); 

【讨论】:

  • 感谢 Eliseo,我想这就是我想要的。现在我的问题是我对svgData 所做的事情是立即返回它(假设我的onButtonClick 返回Promise&lt;string&gt;)。如何让setTimeout 返回我需要的东西?
  • 是一样的,你需要使用"then"里面的setTimeout或者如果你在subscribe里面使用observables
  • 是的,这行得通!我一直在使用awaits,所以我的代码最终看起来像这样:const svgCode = await new Promise&lt;string&gt;(resolve =&gt; { setTimeout(() =&gt; { resolve(document.getElementById('my-component-id').innerHTML)); }); }); 非常感谢,@Eliseo
猜你喜欢
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2019-05-14
  • 2022-06-24
  • 2019-04-18
  • 2017-03-12
相关资源
最近更新 更多