我得到了一个header-comp,一个服务和一个content-comp。在标头组合中,我在服务中切换一个布尔变量以显示或隐藏移动菜单(响应式(。
我想听这个布尔值从内容组合中的变化,它可以工作,但前提是我在服务构造函数中触发它:
export class AppService {
public mblMenuVisible: boolean = false;
public mobileLayout: boolean;
constructor() {
this.determineLayout();
setTimeout(()=>{
this.mblMenuVisible = true;
}, 3000);
}
toggleMblMenu() {
if (this.mblMenuVisible) {
this.mblMenuVisible = false;
} else {
this.mblMenuVisible = true;
}
}
如果我通过 toggleMblMenu(( 手动切换它,我的内容组合不会对此更改做出反应。 content-comp 中的 ngClass 应该对此更改做出反应:
<div [ngClass]="(service.mblMenuVisible===true)?'mbl-content-wrapper':'content-wrapper'">
编辑:
我试过了:
更改检测:更改检测策略.默认
标记检查((
通过主题,它只在标题中工作。
依赖项也是最新的
页眉:
import {ChangeDetectorRef, Component, HostListener, OnInit} from '@angular/core';
import {AppService} from "../shared/appService";
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css'],
providers: [AppService]
})
export class HeaderComponent implements OnInit {
private mobileMenuVisible: boolean;
constructor(private service: AppService,
private cd: ChangeDetectorRef) {
}
ngOnInit() {
this.service.layoutAction.subscribe(
(visible: boolean) => {
this.mobileMenuVisible = visible;
});
}
@HostListener('window:resize', ['$event']) resize(e) {
this.service.determineLayout();
this.cd.detectChanges();
if (!this.service.mobileLayout) {
this.service.mblMenuVisible = false;
}
}
}
服务:
import {Injectable} from "@angular/core";
import {Subject} from "rxjs";
@Injectable()
export class AppService {
public layoutAction = new Subject<boolean>();
public mblMenuVisible: boolean = false;
public mobileLayout: boolean;
constructor() {
this.determineLayout();
}
//LAYOUT
determineLayout() {
if (window.innerWidth > 800) {
this.mobileLayout = false
} else {
this.mobileLayout = true;
}
}
toggleMblMenu (){
this.mblMenuVisible = !this.mblMenuVisible;
this.layoutAction.next(this.mblMenuVisible);
}
}
内容:
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core';
import {AppService} from "../shared/appService";
@Component({
selector: 'app-content',
templateUrl: './content.component.html',
styleUrls: ['./content.component.css'],
providers: [ AppService ],
changeDetection: ChangeDetectionStrategy.Default
})
export class ContentComponent implements OnInit {
private mobileMenuVisible: boolean;
constructor(private service: AppService,
private cd: ChangeDetectorRef) {
}
ngOnInit() {
this.service.layoutAction.subscribe(
(visible: boolean) => {
alert(visible);
this.mobileMenuVisible = visible;
this.cd.markForCheck();
});
}
}
在 HTML 文件中,您应该绑定到mblMenuVisible
而不是service.mblMenuVisible
,因为toggleMblMenu
方法中,您正在更改mblMenuVisible
而不是service.mblMenuVisible
TLDR:使用Angular FlexLayout响应式功能是解决此移动问题的一个非常好的工具箱。
新响应, 现在看看你在最近的编辑中添加的这段代码,
@Injectable()
export class AppService {
...
determineLayout() {
if (window.innerWidth > 800) {
this.mobileLayout = false
} else {
this.mobileLayout = true;
}
}
...
}
@Component()
export class AppComponent{
constructor(private service:AppService){}
...
@HostListener('window:resize', ['$event'])
resize(e) {
this.service.determineLayout();
//this.cd.detectChanges();
if (!this.service.mobileLayout) {
this.service.mblMenuVisible = false;
}
}
...
}
这种需求可以通过Angular FlexLayout响应式功能来满足。
使用 Angular flex 设置您的 Angular 项目后, 可以编写类似此示例的响应指令,
<div fxShow.lt-md fxHide fxFlex >
<!-- MobileMenu Contents -->
</div>
<div fxShow fxHide.lt-md fxFlex >
<!-- DesktopMenu Contents -->
</div>
Angular FlexLayout 响应指令是针对您在此处执行的操作而制定的,无需手动侦听窗口调整大小事件并触发布尔值更改即可让您的组件响应媒体查询断点。
此外,有一种纯 css 方法可以通过香草媒体查询来实现这一点。
只是您的服务需要成为所有组件的全局服务,只需将此AppService
添加到 AppModule 提供程序列表并从组件装饰器中删除providers: [ AppService ],
,因为这样您就可以创建两个不同的对象而不是一个对象,并且在 sigle on 上更改 te 值不会反映另一个,但是当您将服务添加到 appModule 时,将只创建一次,现在您将在所有组件中具有相同的引用
@Injectable({
providedIn:'root'
})
AppService {
...
}
单一实例服务 单一实例服务是以下服务的 应用中仅存在一次实例。
演示 🚀🚀
在演示中拖曳组件(a,b(更改属性的值mblMenuVisible
并且thire组件已注入此服务并对值的更改做出反应以显示或隐藏名为menu的示例组件,该值的主要原因是更改,因为注入的AppService
是同一对象