6

在将 AngularBreakpointObserver与 结合使用时,我尝试使用 Material Design-spec 断点(例如,Angular Material它们在 中定义)。BreakpointsBreakpoints.LandscapePortraitBreakpoints.HandsetPortrait

breakpointObserver 工作,除了当我新加载页面。breakpointObserver 仅在观察到更改触发,但考虑到它是新负载,因此还没有更改。这意味着尚未根据断点评估初始视口。我试过使用 single BreakpointObserver.isMatchedin OnInit,但这似乎没有任何效果。

我将BreakpointObserver,Breakpoints和包含MediaMatcher到一个共享服务中,我订阅了所有需要“监听”断点的组件。

我的问题是:如何确保在第一次视口更改之前评估断点(如果用户不调整窗口大小/更改设备方向,这可能根本不会发生)?

这是我的代码shared.service.ts

import {Component, OnDestroy, OnInit, Injectable,Input,Output,EventEmitter} from '@angular/core';
import {BreakpointObserver, Breakpoints, MediaMatcher} from '@angular/cdk/layout';

@Injectable()
export class SharedService implements OnDestroy, OnInit {
    public isCollapsed = false;
    public isOpen = false;
    public isMobileView = false;
    public isTabletView = false;
    private breakpointObserver: BreakpointObserver;
    @Output() mediaChange = new EventEmitter();
    constructor(breakpointObserver: BreakpointObserver) {
        this.breakpointObserver = breakpointObserver;
        // check if the viewport matches Material Design-spec handset displays
        this.breakpointObserver.observe([
          Breakpoints.HandsetPortrait
        ]).subscribe(result => {
          if (result.matches) {
            this.isMobileView = true;
            this.isTabletView = false;
            this.isOpen = false;
            this.isCollapsed = false;
          }
          else {
            this.isMobileView = false;
            this.isOpen = true;
            this.isCollapsed = false;
          }
          this.mediaChanged();
        });
        // check if the viewport matches Material Design-spec tablet displays
        this.breakpointObserver.observe([
          Breakpoints.TabletPortrait
        ]).subscribe(result => {
          if (result.matches) {
            this.isTabletView = true;
            this.isMobileView = false;
            this.isOpen = true;
            this.isCollapsed = true;
          }
          else {
            if(!this.isMobileView){
                this.isOpen = true;
            }
            this.isTabletView = false;
            this.isCollapsed = false;
          }
          this.mediaChanged();
        });
    }
    mediaChanged() {
        this.mediaChange.emit({
          "isMobileView" : this.isMobileView,
          "isTabletView" : this.isTabletView,
          "isCollapsed" : this.isCollapsed,
          "isOpen" : this.isOpen
      });
    }
    ngOnInit() {
        // MY ATTEMPT
        // Running the same checks as the observer, but this time on init(?)
        // does not seem to take any effect
        if(this.breakpointObserver.isMatched([
          Breakpoints.HandsetPortrait
        ])){
            this.isMobileView = true;
            this.isTabletView = false;
            this.isOpen = false;
            this.isCollapsed = false;
        }
        if(this.breakpointObserver.isMatched([
          Breakpoints.TabletPortrait
        ])){
            this.isTabletView = true;
            this.isMobileView = false;
            this.isOpen = true;
            this.isCollapsed = true;
        }
        this.mediaChanged();
    }
}
4

1 回答 1

2

将局部变量设置为 false 并根据订阅中的值对其进行更改。

import { Component, OnInit } from '@angular/core';
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-main-menu',
  templateUrl: './main-menu.component.html',
  styleUrls: ['./main-menu.component.css']
})
export class MainMenuComponent implements OnInit {
  isHandset = false;

  constructor(private breakpointObserver: BreakpointObserver, private route: ActivatedRoute) {}

  ngOnInit() {
    this.breakpointObserver.observe(Breakpoints.Handset)
      .subscribe((state: BreakpointState) => {
        if (state.matches) {
          this.isHandset = true;
        } else {
          this.isHandset = false;
        }
      });
  }

}

模板代码:

<mat-sidenav-container class="sidenav-container">
  <mat-sidenav #drawer class="sidenav" fixedInViewport
      [attr.role]="isHandset ? 'dialog' : 'navigation'"
      [mode]="isHandset ? 'over' : 'side'"
      [opened]="isHandset === false">
    <mat-toolbar>Menu</mat-toolbar>
    <mat-nav-list>
      <a mat-list-item href="#">Link 1</a>
      <a mat-list-item href="#">Link 2</a>
      <a mat-list-item href="#">Link 3</a>
    </mat-nav-list>
  </mat-sidenav>
  <mat-sidenav-content>
    <mat-toolbar color="primary">
      <button
        type="button"
        aria-label="Toggle sidenav"
        mat-icon-button
        (click)="drawer.toggle()"
        *ngIf="isHandset">
        <mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
      </button>
      <span>timplaw-dotcom</span>
    </mat-toolbar>
    <!-- Add Content Here -->
    <router-outlet></router-outlet>
  </mat-sidenav-content>
</mat-sidenav-container>

参考:https ://alligator.io/angular/breakpoints-angular-cdk/

于 2019-07-17T22:35:20.007 回答