【问题标题】:Angular resize service角度调整服务
【发布时间】:2021-08-25 12:12:04
【问题描述】:

我正在尝试创建一个 observable,如果窗口屏幕小于 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 仅在 resize 事件中创建。你知道如何实现这个功能吗?

【问题讨论】:

  • 请使用三重反引号包装器 ` ` code ` ` ` 粘贴您的代码(中间没有空格)

标签: angular typescript components observable behaviorsubject


【解决方案1】:

您实际上不需要那么多代码,您可以直接在服务中将truefalse 分配给您在组件中订阅的可观察对象。假设您想根据移​​动/桌面视图在模板中显示不同的内容,那么使用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 - 这里只考虑屏幕宽度以便于测试:)

【讨论】:

  • 非常感谢,您的代码非常干净。但是你能解释一下为什么我需要在管道中使用 mapTo(window) 运算符吗?是因为 observable 发出一个 Event 对象而我实际上需要一个 windows 对象吗?抱歉,我是 RxJS 的新手,我认为所有这些操作符都让我着迷……
  • 正如我添加的评论,映射到窗口,所以我们可以有初始值。如果您删除 startWithmapTo 它最初不会触发,因为在页面加载时没有发生调整大小。我们在这里使用window,因为当页面加载时,没有可用的调整大小事件(还),因为调整大小还没有发生
【解决方案2】:

您应该使用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 了解有关如何使用生命周期挂钩的更多详细信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 2015-07-14
    • 2014-12-31
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    相关资源
    最近更新 更多