将窗口 MutationObserver 与 Angular HostBinding 一起使用时,选项卡崩溃

Tab crashes when using window MutationObserver with Angular HostBinding

提问人:Orst 提问时间:8/15/2023 最后编辑:kvetisOrst 更新时间:8/15/2023 访问量:68

问:

在将 MutationObserver 添加到我的应用程序时,我遇到了一个非常奇怪的错误。 我的一个 Angular 组件是将 HostBinding 用于元素的 attr.style 属性,这与我注入页面的突变观察器(来自另一个 js 文件)一起工作,直到几天前我将 attributes 标志设置为 true 突变观察器,然后选项卡完全崩溃并陷入循环。 我不确定为什么,突变观察者不应该引起或触发任何新事件,它应该只观察,所以我不明白监听页面中元素的属性会导致它,除非它做的不仅仅是听?

我设置了一个快速演示,有 2 个 HostBindings,第一个与问题无关,主要问题是绑定到 attr.style。 如果要重新创建 bug,请将观察者的 attributes 标志设置为 true。

https://stackblitz.com/edit/angular-hostbinding-class-demo-ud5m8g?file=src%2Fapp%2Fhello.component.ts

任何帮助将不胜感激,谢谢!

我试图将属性标志设置为false,它确实有帮助,我只是不明白为什么。我需要继续使用那个标志。另一种选择是删除该绑定,稍后手动设置该 css 规则。

@Component({
  selector: 'hello',
  template: `<h1 >This is a {{name}}!!!</h1>
  <button (click)='activate()'>Activate</button>`,
  styles: [
    `
   h1 { font-family: montserrat;}`,
  ],
})
export class HelloComponent implements OnInit {
  @Input() name: string;
  toggle: boolean;
  toogle: boolean;

  @HostBinding('class.Current')
  get t() {
    console.log('getter-toggle function called');
    return this.toggle;
  }
  @HostBinding('attr.style')
  public get cssVariables() {
    console.log('getter-cssRules function called');
    const cssVariables = `
    --sq-color: blue
    `;
    return this.sanitizer.bypassSecurityTrustStyle(cssVariables);
  }

  constructor(private sanitizer: DomSanitizer) {}

  activate() {
    this.toggle = !this.toggle;
    console.log(this.toggle);
  }

  ngOnInit() {
    let observer = new MutationObserver(this.logChanges);

    observer.observe(window.document.documentElement, {
      childList: true,
      subtree: true,
      attributes: false, // Switch this to true if you want to crash the tab
    });
  }

  logChanges(records, observer) {
    for (const record of records) {
      console.log(record);
    }
  }
}
angular angularjs-指令 webapi 突变-观察者

评论

0赞 Community 8/15/2023
请提供足够的代码,以便其他人可以更好地理解或重现问题。

答:

0赞 kvetis 8/15/2023 #1

首先,非常奇怪的是,您正在从监视包含组件更改的文档更改的组件创建突变观察器。但也许这只是一个示例代码。

每次调用 getter 时都会设置新值,因为清理会创建一个与函数的上一次调用不同的对象。因此,在每次渲染时,都会返回不同的值。@HostBinding('attr.style')

MutationObserver 侦听器中的某些内容使侦听器导致组件重新呈现。这将更改 style 属性,并导致再次调用 MutationObserver 侦听器。我试图在 Angular Zone 之外运行侦听器,但这没有帮助。

有帮助的是只清理一次样式值:

  @HostBinding('attr.style')
  public get cssVariables() {
    console.log('getter-cssRules function called');
    return this.sanitizedValue
  }

  private sanitizedValue = null

  constructor(private sanitizer: DomSanitizer) {
    this.sanitizedValue =  this.sanitizer.bypassSecurityTrustStyle(`
  --sq-color: blue
  `);
  }

这样,即使在观察属性变化时,它也能正常工作。

请参阅带有工作示例的 Stackblitz

评论

1赞 Orst 8/28/2023
感谢您的回复。不幸的是,对我来说,更改 angular 组件本身并没有真正的帮助,因为该产品可以嵌入到客户网站中,所以我无法确保他们不会在他们的应用程序上使用这种绑定。例如,我可以为观察者保留属性:false,也可以开始检查客户的网站并检查ngZone是否存在。这是一项相当大的任务,因为 react 也使用虚拟 DOM,例如,我还没有在那里测试这个错误。