Angular 2:检测浏览器宽度的变化并更新模型

Posted

技术标签:

【中文标题】Angular 2:检测浏览器宽度的变化并更新模型【英文标题】:Angular 2: Detect changes in browser width and update model 【发布时间】:2017-01-25 19:17:46 【问题描述】:

在我的Angular 2 应用程序中,我根据浏览器窗口宽度更改样式。这是一个示例(SCSS):

.content
    /*styles for narrow screens*/
    @media (max-width: 750px)
        background-color:beige;
    
    /*styles for medium screens*/
    @media (min-width: 751px) and (max-width: 1200px) 
        background-color:red;
    
    /*styles for wide screens*/
    @media (min-width: 1201px) 
        background-color:brown;
       

这使我的 UI 具有响应性。我希望我的 Angular 组件知道当前的宽度间隔:

/* Returns which of the CSS width intervals is current*/
getWidthRange()
    let pixelWidth = ...; //what goes here?

    if(pixelWidth < 251) return "small";
    if(pixelWidth < 451) return "medium";
    return "large"; 
   

组件会调用此函数并根据宽度调整其行为。例如,下面的模板将在更宽的屏幕上显示更多内容:

<div>
    getWidthRange()==='small'? shortText : longText
</div>

更好的是,我会设置一个 Observable,它会在浏览器从一个范围转换到下一个范围时发出:

widthRangeChanges = Observable.create( observer => 
           
        // ? how to detect when width changes
        let oldRange = '...';
        let newRange = '...';
        if(newRange!==oldRange) observer.next(newRange);
    
).share(); //all subscribers share same output channel

然后组件可以订阅widthRangeChanges 并在收到新范围时更新模型值。我如何在Angular 2 中获取此信息?

Angular 2 rc-6typescript 2.0.2rxjs 5 beta 11

【问题讨论】:

【参考方案1】:

你可以使用RxJS的fromEvent操作符:

 const $resizeEvent = Observable.fromEvent(window, 'resize')
   .map(() => 
     return document.documentElement.clientWidth;
   )
   .debounceTime(200)

   $resizeEvent.subscribe(data => 
     this.width = data;
   );

Plunker Example

【讨论】:

感谢您的提示。我不知道fromEvent。这些事件是 RxJS 专有的,还是我可以通过这种方式将任何 JS 事件转换为 Observable? 我猜它只适用于 DOM 事件 这是一个很棒的提示,Plunker 也是如此。我会试试看。这是一个使答案更有帮助的链接:reactivex.io/rxjs/class/es6/… 我使用了您的解决方案。不过没有必要使用mapfromEvent 可以接受第三个参数,一个返回您希望 Observable 发出的内容的函数。请参阅plnkr.co/edit/lgkRt8nNMScPOH7QmrBS?p=preview 谢谢,非常优雅的解决方案!只有一件事:在现代 Angular 版本中,您应该使用这种方法导入 fromEvent、map 和 debounceTime:***.com/questions/50571550/…【参考方案2】:

模板

<div (window:resize)="onResize($event)"></div>

export class AppComponent             
      onResize(event) 
        console.log(event);
        console.log("width:" + event.target.innerWidth);
        console.log("height:" + event.target.innerHeight);

        this.pixelWidth = event.target.innerWidth;
      

      getWidthRange()
         if(this.pixelWidth < 251) return "small";
         if(this.pixelWidth < 451) return "medium";
         return "large"; 
      

【讨论】:

我从未见过这种(window:resize) 事件绑定表示法。这是标准Angular 2吗? (任何指向官方文档的链接都会有所帮助) 我曾在某处阅读过其中一个 beta 版本(现在我不记得参考了)。后来在我的项目中实现。我猜文档还没有。【参考方案3】:
getWidth() 
    return Math.max(
      document.body.scrollWidth,
      document.documentElement.scrollWidth,
      document.body.offsetWidth,
      document.documentElement.offsetWidth,
      document.documentElement.clientWidth
    );

【讨论】:

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。

以上是关于Angular 2:检测浏览器宽度的变化并更新模型的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 变化检测与 observables

Angular 2 - 模型更改后视图不更新

在Angular中更改模型后如何更新视图?

Angular 2,Eventemitter 会触发变化检测吗?

检测模型的变化[重复]

浅析$watch ,$apply 和 $digest (Angular篇)