Angular 通用 - 不应使用超时
Angular Universal - timeout should not be used
所以我一直在尝试将我的应用程序转换为 angular 通用,并且在大多数情况下都很好。
但是我之前读了一些"gotchas":https://github.com/onespeed-articles/angular-universal-gotchas
它建议我不应该使用 timeout
这很烦人,因为在 angularjs 中你用它来让东西在视图后触发已渲染,因此您可以确定元素的尺寸是否正确等。
我还读到它仍然存在于 angular 6 所以我有这个指令:
import { Directive, ElementRef, AfterViewInit, Input, HostListener } from '@angular/core';
@Directive({
selector: '[pyb-button-group]'
})
export class ButtonGroupDirective implements AfterViewInit {
@Input() className: string;
@HostListener('window:resize', ['$event'])
onResize() {
let resize = this.resize;
let element = this.element;
let className = this.className;
setTimeout(function () {
resize(element, className);
}, 500);
}
constructor(private element: ElementRef) {
}
ngAfterViewInit() {
this.resize(this.element, this.className);
}
resize(nativeElement, className) {
let elements = nativeElement.nativeElement.getElementsByClassName(className || 'btn-choice');
let headerHeight = 0;
for (var i = 0; i < elements.length; i++) {
let element = elements[i];
let header = element.getElementsByClassName('header');
if (!header.length) return;
header = header[0];
header.style.height = 'auto'; // Reset when resizing the window
let height = header.offsetHeight;
if (height > headerHeight) headerHeight = height;
}
for (var i = 0; i < elements.length; i++) {
let element = elements[i];
let header = element.getElementsByClassName('header');
if (!header.length) return;
header = header[0];
header.style.height = headerHeight + 'px';
}
}
}
当浏览器调整大小时,它会等待 0.5 秒,然后再尝试调整按钮组的大小。
如果这是不好的做法,我应该改用什么?
您希望该代码 运行 在浏览器中而不是在服务器中。您提供的 link 给出了解决方案:
if (isPlatformBrowser(this.platformId)) {
//your setTimeout here
}
When the browser resizes, it waits for .5 of a second before it tries to resize the button group. If this is bad practice, what should I use instead?
您正在延迟 每个 调整大小事件。通常,您希望每 500 毫秒去抖并只处理一个事件。这可以使用 observable 来完成,但请确保在组件被销毁时取消订阅。
observableFromEvent(window, 'resize')
.pipe(debounceTime(500))
.subscribe(() => this.resize(this.element, this.className))
另外 @HostListener()
在服务器端呈现期间从不触发事件。服务器上没有 DOM 触发 window 调整大小事件。
setTimeout(function () {
resize(element, className);
}, 500);
您在此处使用的 setTimeout
全局函数在 NodeJS 中具有不同的函数签名。当您 运行 Angular Universe 中的应用程序时,它 运行 在 NodeJS 内部生成 HTML ,然后再进入 Web 浏览器。 setTimeout returns Web 浏览器上的数字,但 returns NodeJS 中的资源句柄。
如果您打算 运行 在 Angular Universal 中使用您的应用程序,那么这意味着您正在编写与 Web 浏览器分离的源代码。这意味着没有直接操作 DOM,没有全局变量,也没有全局 window 变量。
所以我一直在尝试将我的应用程序转换为 angular 通用,并且在大多数情况下都很好。 但是我之前读了一些"gotchas":https://github.com/onespeed-articles/angular-universal-gotchas
它建议我不应该使用 timeout
这很烦人,因为在 angularjs 中你用它来让东西在视图后触发已渲染,因此您可以确定元素的尺寸是否正确等。
我还读到它仍然存在于 angular 6 所以我有这个指令:
import { Directive, ElementRef, AfterViewInit, Input, HostListener } from '@angular/core';
@Directive({
selector: '[pyb-button-group]'
})
export class ButtonGroupDirective implements AfterViewInit {
@Input() className: string;
@HostListener('window:resize', ['$event'])
onResize() {
let resize = this.resize;
let element = this.element;
let className = this.className;
setTimeout(function () {
resize(element, className);
}, 500);
}
constructor(private element: ElementRef) {
}
ngAfterViewInit() {
this.resize(this.element, this.className);
}
resize(nativeElement, className) {
let elements = nativeElement.nativeElement.getElementsByClassName(className || 'btn-choice');
let headerHeight = 0;
for (var i = 0; i < elements.length; i++) {
let element = elements[i];
let header = element.getElementsByClassName('header');
if (!header.length) return;
header = header[0];
header.style.height = 'auto'; // Reset when resizing the window
let height = header.offsetHeight;
if (height > headerHeight) headerHeight = height;
}
for (var i = 0; i < elements.length; i++) {
let element = elements[i];
let header = element.getElementsByClassName('header');
if (!header.length) return;
header = header[0];
header.style.height = headerHeight + 'px';
}
}
}
当浏览器调整大小时,它会等待 0.5 秒,然后再尝试调整按钮组的大小。 如果这是不好的做法,我应该改用什么?
您希望该代码 运行 在浏览器中而不是在服务器中。您提供的 link 给出了解决方案:
if (isPlatformBrowser(this.platformId)) {
//your setTimeout here
}
When the browser resizes, it waits for .5 of a second before it tries to resize the button group. If this is bad practice, what should I use instead?
您正在延迟 每个 调整大小事件。通常,您希望每 500 毫秒去抖并只处理一个事件。这可以使用 observable 来完成,但请确保在组件被销毁时取消订阅。
observableFromEvent(window, 'resize')
.pipe(debounceTime(500))
.subscribe(() => this.resize(this.element, this.className))
另外 @HostListener()
在服务器端呈现期间从不触发事件。服务器上没有 DOM 触发 window 调整大小事件。
setTimeout(function () {
resize(element, className);
}, 500);
您在此处使用的 setTimeout
全局函数在 NodeJS 中具有不同的函数签名。当您 运行 Angular Universe 中的应用程序时,它 运行 在 NodeJS 内部生成 HTML ,然后再进入 Web 浏览器。 setTimeout returns Web 浏览器上的数字,但 returns NodeJS 中的资源句柄。
如果您打算 运行 在 Angular Universal 中使用您的应用程序,那么这意味着您正在编写与 Web 浏览器分离的源代码。这意味着没有直接操作 DOM,没有全局变量,也没有全局 window 变量。