问题描述
@property({type: Number}) ScreenSizeEnum = ScreenSize.Desktop;
@property({type: Array}) menuData: IMenu[] = [];
@property({type: Boolean}) isMobileMenuOpen: boolean = false;
constructor() {
super();
}
connectedCallback() {
super.connectedCallback();
window.addEventListener('resize',this.onResizeEvent);
}
disconnectedCallback() {
window.removeEventListener('resize',this.onResizeEvent);
super.disconnectedCallback();
}
onResizeEvent() {
let oldVal = this.ScreenSizeEnum;
if (window.outerWidth > 1000) {
this.ScreenSizeEnum = ScreenSize.Desktop;
} else if (window.outerWidth > 700 && window.outerWidth < 1000) {
//Tablet
this.ScreenSizeEnum = ScreenSize.Tablet;
} else if (window.outerWidth < 700) {
// mobile
this.ScreenSizeEnum = ScreenSize.Mobile;
}
}
render() {
let device = this.getDeviceType();
if (device == "desktop" || this.ScreenSizeEnum == ScreenSize.Desktop) {
return html`
<nav class="animate__animated animate__bounce animate__slow">
<ul class="menu-ul">
${this.menuData.map(
menuItem => html`
<universe-menu-main .linkText="${menuItem.linkText}" .link="${menuItem.link}" .subMenu="${menuItem.subMenu}"></universe-menu-main>
`
)}
</ul>
</nav>
`
} else if (device == 'tablet' || this.ScreenSizeEnum == ScreenSize.Tablet) {
return html`
<tablet-menu .menuData="${this.menuData}"></tablet-menu>
`;
} else if (device == 'mobile' || this.ScreenSizeEnum == ScreenSize.Mobile) {
return html`
<mobile-menu .menuData="${this.menuData}" .isOpen="${this.isMobileMenuOpen}"></mobile-menu>
`;
}
}
getDeviceType() {
const ua = navigator.userAgent;
if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {
return "tablet";
}
if (
/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(
ua
)
) {
return "mobile";
}
return "desktop";
};
将触发resize事件,但是只要更改ScreenSizeEnum
,render
函数就不会运行。
为什么会发生这种情况,我该如何解决?
解决方法
您的问题在于您如何订阅事件以及 CompletableFuture.allOf(wait);
在 JS 中的时髦行为:
this
这意味着在 window.addEventListener('resize',this.onResizeEvent);
中,术语 onResizeEvent()
将指正在调整大小的窗口,而不是您的组件。
您可以通过使用 lambda 来强制使用 this
上下文来解决此问题(因为在 this
主体内部,=>
始终是当前上下文,而不是事件的上下文:
this
现在,当 window.addEventListener('resize',() => this.onResizeEvent());
事件触发时,其中的 onResizeEvent()
将引用控件,而不是窗口。
问题是现在您无法取消订阅。我们需要保留对包装方法的引用以将其删除:
this
由于这是导致更新的外部事件,因此更适合 ReactiveController
触发窗口事件的更新,并将所有这些调整大小的代码与您的组件隔离。