Angular 调整服务大小
Angular resize service
我正在尝试创建一个 Observable,如果 window 屏幕小于或小于 520 像素,它将发出 true 或 false 值。
所以我有下面的代码:
@Injectable({
providedIn: 'root'
})
export class ResizeService {
private mobileView$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
mobileViewObs$ = this.mobileView$.asObservable();
isMobile = false;
size!: {width: number, height: number};
constructor() {
}
resizeEvent(){
fromEvent(window, 'resize').pipe(throttleTime(500), debounceTime(500)).subscribe((resizeEvent: any) => {
this.size = {
width: +resizeEvent.currentTarget.innerWidth,
height: +resizeEvent.currentTarget.innerHeight
};
this.isMobile = this.isMobileView(this.size);
this.mobileView$.next(this.isMobile);
});;
}
isMobileView(size: {width: number, height: number}){
if(size.width < PHONE_SIZE.width && size.height < PHONE_SIZE.height){
return true;
} else {
return false;
}
}
}
它工作正常,但问题是我无法设置页面的初始大小。我不知道如何将尺寸对象从组件发送到服务。这是我的 component.ts:
@Component({
selector: 'app-books-list',
templateUrl: './books-list.component.html',
styleUrls: ['./books-list.component.scss'],
})
export class BooksListComponent implements OnInit {
@Input() book!: BookModel;
booksArray: BookModel[] = [];
oneBook!: BookModel;
isMobile: boolean = false;
size!: {width: number, height: number};
constructor(private service: BookService, private route: ActivatedRoute,
private resizeService: ResizeService) {}
ngOnInit(): void {
this.size = {width: window.innerWidth, height: window.innerHeight};
this.resizeService.resizeEvent();
this.resizeService.mobileViewObs$.subscribe(data => {
this.isMobile = data;
})
this.service.getBooks().subscribe((books) => {
this.booksArray = books;
});
}
问题是第一次重新加载页面时它总是显示为 false,因为 observable 仅在调整大小事件时创建。你知道如何实现这个功能吗?
您应该使用 ngAfterViewInit
而不是 ngOnInit
。您需要在组件开始渲染时获取尺寸。但是,ngOnInit
用于初始化所有数据绑定属性。
@Component({
selector: 'app-books-list',
templateUrl: './books-list.component.html',
styleUrls: ['./books-list.component.scss'],
})
export class BooksListComponent implements OnInit, AfterViewInit {
@Input() book!: BookModel;
booksArray: BookModel[] = [];
oneBook!: BookModel;
isMobile: boolean = false;
size!: {width: number, height: number};
constructor(private service: BookService, private route: ActivatedRoute,
private resizeService: ResizeService) {}
ngOnInit(): void {
this.size = {width: window.innerWidth, height: window.innerHeight};
this.service.getBooks().subscribe((books) => {
this.booksArray = books;
});
ngAfterViewInit() {
// removed this from ViewInit
this.resizeService.resizeEvent();
this.resizeService.mobileViewObs$.subscribe(data => {
this.isMobile = data;
})
}
}
查看 here 了解有关如何使用生命周期挂钩的更多详细信息。
实际上您不需要那么多代码,您可以直接在服务中将 true
或 false
分配给您在组件中订阅的可观察对象。假设您想根据 mobile/desktop 视图在模板中显示不同的内容,那么使用 async
管道是一个完美的场景!
如果你需要组件ts中的true
/false
,你当然可以订阅,但记得取消订阅你正在走的路!
无论如何,我建议如下...
服务:
isMobile$ = fromEvent(window, 'resize').pipe(
startWith(window), // to have an initial value, can be any value
mapTo(window), // map to window object instead (so we can have the initial value!)
throttleTime(500),
debounceTime(500),
map((window: Window) => {
if (window.innerWidth < PHONE_SIZE.width && window.innerHeight < PHONE_SIZE.height) {
return true;
}
return false;
})
);
在组件中你只需要做....
isMobile$ = this.resizeService.isMobile$;
然后使用 async
管道或订阅!
HERE'S A DEMO - 这里只考虑屏幕宽度以便于测试:)
我正在尝试创建一个 Observable,如果 window 屏幕小于或小于 520 像素,它将发出 true 或 false 值。 所以我有下面的代码:
@Injectable({
providedIn: 'root'
})
export class ResizeService {
private mobileView$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
mobileViewObs$ = this.mobileView$.asObservable();
isMobile = false;
size!: {width: number, height: number};
constructor() {
}
resizeEvent(){
fromEvent(window, 'resize').pipe(throttleTime(500), debounceTime(500)).subscribe((resizeEvent: any) => {
this.size = {
width: +resizeEvent.currentTarget.innerWidth,
height: +resizeEvent.currentTarget.innerHeight
};
this.isMobile = this.isMobileView(this.size);
this.mobileView$.next(this.isMobile);
});;
}
isMobileView(size: {width: number, height: number}){
if(size.width < PHONE_SIZE.width && size.height < PHONE_SIZE.height){
return true;
} else {
return false;
}
}
}
它工作正常,但问题是我无法设置页面的初始大小。我不知道如何将尺寸对象从组件发送到服务。这是我的 component.ts:
@Component({
selector: 'app-books-list',
templateUrl: './books-list.component.html',
styleUrls: ['./books-list.component.scss'],
})
export class BooksListComponent implements OnInit {
@Input() book!: BookModel;
booksArray: BookModel[] = [];
oneBook!: BookModel;
isMobile: boolean = false;
size!: {width: number, height: number};
constructor(private service: BookService, private route: ActivatedRoute,
private resizeService: ResizeService) {}
ngOnInit(): void {
this.size = {width: window.innerWidth, height: window.innerHeight};
this.resizeService.resizeEvent();
this.resizeService.mobileViewObs$.subscribe(data => {
this.isMobile = data;
})
this.service.getBooks().subscribe((books) => {
this.booksArray = books;
});
}
问题是第一次重新加载页面时它总是显示为 false,因为 observable 仅在调整大小事件时创建。你知道如何实现这个功能吗?
您应该使用 ngAfterViewInit
而不是 ngOnInit
。您需要在组件开始渲染时获取尺寸。但是,ngOnInit
用于初始化所有数据绑定属性。
@Component({
selector: 'app-books-list',
templateUrl: './books-list.component.html',
styleUrls: ['./books-list.component.scss'],
})
export class BooksListComponent implements OnInit, AfterViewInit {
@Input() book!: BookModel;
booksArray: BookModel[] = [];
oneBook!: BookModel;
isMobile: boolean = false;
size!: {width: number, height: number};
constructor(private service: BookService, private route: ActivatedRoute,
private resizeService: ResizeService) {}
ngOnInit(): void {
this.size = {width: window.innerWidth, height: window.innerHeight};
this.service.getBooks().subscribe((books) => {
this.booksArray = books;
});
ngAfterViewInit() {
// removed this from ViewInit
this.resizeService.resizeEvent();
this.resizeService.mobileViewObs$.subscribe(data => {
this.isMobile = data;
})
}
}
查看 here 了解有关如何使用生命周期挂钩的更多详细信息。
实际上您不需要那么多代码,您可以直接在服务中将 true
或 false
分配给您在组件中订阅的可观察对象。假设您想根据 mobile/desktop 视图在模板中显示不同的内容,那么使用 async
管道是一个完美的场景!
如果你需要组件ts中的true
/false
,你当然可以订阅,但记得取消订阅你正在走的路!
无论如何,我建议如下...
服务:
isMobile$ = fromEvent(window, 'resize').pipe(
startWith(window), // to have an initial value, can be any value
mapTo(window), // map to window object instead (so we can have the initial value!)
throttleTime(500),
debounceTime(500),
map((window: Window) => {
if (window.innerWidth < PHONE_SIZE.width && window.innerHeight < PHONE_SIZE.height) {
return true;
}
return false;
})
);
在组件中你只需要做....
isMobile$ = this.resizeService.isMobile$;
然后使用 async
管道或订阅!
HERE'S A DEMO - 这里只考虑屏幕宽度以便于测试:)