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

问题描述 投票:0回答:1

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

我设置了一个快速演示,有2个HostBindings,第一个与问题无关,主要问题是与attr.style的绑定。 如果您想重新创建错误,请将观察者的属性标志设置为 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-directive webapi mutation-observers
1个回答
0
投票

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

每次调用 getter 时,

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

MutationObserver 侦听器中的某些内容使侦听器导致组件重新渲染。这会更改样式属性并导致 MutationObserver 侦听器再次被调用。我尝试在角度区域之外运行侦听器,但这没有帮助。

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

  @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 和工作示例

© www.soinside.com 2019 - 2024. All rights reserved.