提问人:Orst 提问时间:8/15/2023 最后编辑:kvetisOrst 更新时间:8/15/2023 访问量:68
将窗口 MutationObserver 与 Angular HostBinding 一起使用时,选项卡崩溃
Tab crashes when using window MutationObserver with Angular HostBinding
问:
在将 MutationObserver 添加到我的应用程序时,我遇到了一个非常奇怪的错误。 我的一个 Angular 组件是将 HostBinding 用于元素的 attr.style 属性,这与我注入页面的突变观察器(来自另一个 js 文件)一起工作,直到几天前我将 attributes 标志设置为 true 突变观察器,然后选项卡完全崩溃并陷入循环。 我不确定为什么,突变观察者不应该引起或触发任何新事件,它应该只观察,所以我不明白监听页面中元素的属性会导致它,除非它做的不仅仅是听?
我设置了一个快速演示,有 2 个 HostBindings,第一个与问题无关,主要问题是绑定到 attr.style。 如果要重新创建 bug,请将观察者的 attributes 标志设置为 true。
任何帮助将不胜感激,谢谢!
我试图将属性标志设置为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);
}
}
}
答:
首先,非常奇怪的是,您正在从监视包含组件更改的文档更改的组件创建突变观察器。但也许这只是一个示例代码。
每次调用 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
`);
}
这样,即使在观察属性变化时,它也能正常工作。
评论