dom完成渲染后Angular2执行操作

Posted

技术标签:

【中文标题】dom完成渲染后Angular2执行操作【英文标题】:Angular2 do actions after dom has finished rendering 【发布时间】:2019-04-27 21:25:31 【问题描述】:

我在页面上有一个大型 ngx-bootstrap 手风琴。当我打开一些较低的手风琴时,我希望它滚动页面,以便打开的手风琴从窗口顶部开始。我用scrollIntoView实现了滚动部分,但现在的问题是在正确的时间执行它。我目前在 ngAfterViewChecked 中执行此操作,但 viewChecked 被多次触发(mousemove、mouseenter 等)。有没有办法仅在 DOM 完成与 angular2+ changeDetection 分开渲染后才触发一段代码?

解决方案

这是开始起作用的解决方案。

constructor(elementRef: ElementRef) 
    this.elementRef = elementRef
  

getData()
   this.getService().then(result => 
      #do stuff with result
      setTimeout(() => this.scrollToBegin());
    ).catch((err: any) => 
    );


scrollToBegin(): any
      this.elementRef.nativeElement.scrollIntoView();
    

【问题讨论】:

ngOnInit 钩子有什么问题。在显示所有绑定后触发它。更重要的是,它会被触发一次。 但是每次打开手风琴时我都需要触发它。当我打开页面时,所有 ngOnInits 都已完成。之后不再调用它。 【参考方案1】:

查看 Angular 文档以了解不同的生命周期挂钩。组件视图初始化后调用生命周期钩子。

AfterViewInit() 将根据您的要求执行一次。

在 Angular 完成后立即调用的回调方法 完成了组件视图的初始化。它只被调用 视图实例化时一次。

ngAfterVIewChecked() 在组件视图加载后调用,但它会检测到更改并执行。

【讨论】:

【参考方案2】:

AFAIK 你只有 ngAfterViewCheckedngAfterViewInit 来检测 dom 更新。

根据我的经验,有时您需要在 settimeout 中编写用于 dom 更改的代码,以便为此安排宏任务(异步更新),以便您的代码将在下一个更改检测周期中运行(这正是你需要)。更多详情见this article

将您的罐头放在块代码末尾的settimeout 中(并将其从ngAfterViewChecked 中删除)。 一些例子:

setTimeout(() => htmlInputElement.focus()); // focus an input
setTimeout(() => htmlElement.scrollIntoView()); // scroll into view

【讨论】:

当我把它放在 afterViewChecked 里面时它没有工作。但是,如果我将它作为 AJAX 所做的最后一件事添加,它就开始起作用了。 @MarkoTaht 你做对了。我编辑了我的答案以澄清这一点。【参考方案3】:

这是一个愚蠢的回应。但是您是否考虑过使用随手风琴提供的自定义事件isOpenChange

      <accordion-group heading="Group with isOpenChange event listener" 
(isOpenChange)="log($event)">
        <p>Some content</p>
      </accordion-group>

然后在对方:

log(event: boolean) 
    console.log(`Accordion has been $event ? 'opened' : 'closed'`);
  

【讨论】:

我已经在使用它了。 isOpenChange 调用从服务器获取数据的 ajax 调用。我尝试在 ajax 结束时调用 scrollIntoView 事件,但它不起作用,因为它现在正在执行 DOM 更新。 好的。所以这是一个时间问题。你调用了 http 端点并且你想在调用返回时执行一些操作? 来自端点的数据创建一个大表。因此,如果手风琴是列表中的最后一个,您需要手动滚动才能查看内容,如果它会自动在列表中居中会很好。 vmoh_ir 的答案是我正在寻找的解决方案。 这不是解决方案,而是解决方法。调用 set timeout 是实现您想要的非确定性方式。我想找到一个真正的解决方案。因为我将来可能会遇到这个问题。 您能否发布完整的解决方案。现在编写的代码。

以上是关于dom完成渲染后Angular2执行操作的主要内容,如果未能解决你的问题,请参考以下文章

怎么在ng-repeat生成的元素上操作dom

vue 钩子函数执行顺序

页面加载完成后执行javascript [重复]

dom 完成渲染后如何运行指令?

vuex + watch = 监听组件渲染状态

AngularJS - 指令渲染完成后如何查询 DOM