18

Angular2に私の道を進んでいます。私の目的は、デバイスの幅に関するさまざまなメディアクエリに応じて異なるコンポーネントを読み込む応答性の高いアプリケーションを作成することです。 、私はMatchMediaServiceリスナーイベントだけでなく、返すものに応じてロードする子コンポーネント(HomeMobileComponentまたはHomeDesktopComponent)を決定するためにMatchMediaServiceを使用して「親」コンポーネント(HomeComponent)内部次にAngular2で応答性の高いコンポーネントを行う方法

import { Injectable } from '@angular/core'; 

@Injectable() 
export class MatchMediaService 
{ 
    constructor() 
    { 

    } 

    rules = 
    { 
     print: "print", 
     screen: "screen", 
     phone: '(max-width: 767px)', 
     tablet: '(min-width: 768px) and (max-width: 1024px)', 
     desktop: '(min-width: 1025px)', 
     portrait: '(orientation: portrait)', 
     landscape: '(orientation: landscape)', 
     retina: '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)' 
    }; 

    Check = function (mq) 
    { 
     if (!mq) 
     { 
      return; 
     } 

     return window.matchMedia(mq).matches; 
    }; 

/********************************************** 
    METHODS FOR CHECKING TYPE 
**********************************************/ 
    IsPhone() 
    { 
     return window.matchMedia(this.rules.phone).matches; 
    }; 

    IsTablet = function() 
    { 
     return window.matchMedia(this.rules.tablet).matches; 
    }; 

    IsDesktop = function() 
    { 
     return window.matchMedia(this.rules.desktop).matches; 
    }; 

    IsPortrait = function() 
    { 
     return window.matchMedia(this.rules.portrait).matches; 
    }; 

    IsLandscape = function() 
    { 
     return window.matchMedia(this.rules.landscape).matches; 
    }; 

    IsRetina = function() 
    { 
     return window.matchMedia(this.rules.retina).matches; 
    }; 


/********************************************** 
    EVENT LISTENERS BY TYPE 
**********************************************/  
    OnPhone(callBack) 
    { 
     if (typeof callBack === 'function') 
     { 
      var mql: MediaQueryList = window.matchMedia(this.rules.phone); 

      mql.addListener((mql: MediaQueryList) => 
      { 
       if (mql.matches) 
       { 
        callBack(mql); 
       } 
      }); 
     } 
    }; 

    OnTablet(callBack) 
    { 
     if (typeof callBack === 'function') 
     { 
      var mql: MediaQueryList = window.matchMedia(this.rules.tablet); 

      mql.addListener((mql: MediaQueryList) => 
      { 
       if (mql.matches) 
       { 
        callBack(mql); 
       } 
      }); 
     } 
    }; 

    OnDesktop(callBack) 
    { 
     if (typeof callBack === 'function') 
     { 
      var mql: MediaQueryList = window.matchMedia(this.rules.desktop); 

      mql.addListener((mql: MediaQueryList) => 
      { 
       if (mql.matches) 
       { 
        callBack(mql); 
       } 
      }); 
     } 
    }; 

    OnPortrait(callBack) 
    { 
     if (typeof callBack === 'function') 
     { 
      var mql: MediaQueryList = window.matchMedia(this.rules.portrait); 

      mql.addListener((mql: MediaQueryList) => 
      { 
       if (mql.matches) 
       { 
        callBack(mql); 
       } 
      }); 
     } 
    }; 

    OnLandscape(callBack) 
    { 
     if (typeof callBack === 'function') 
     { 
      var mql: MediaQueryList = window.matchMedia(this.rules.landscape); 

      mql.addListener((mql: MediaQueryList) => 
      { 
       if (mql.matches) 
       { 
        callBack(mql); 
       } 
      }); 
     } 
    }; 
} 

:私の作業の例では、MatchMediaServiceを持っていますその火のブラウザは異なる次元を通じてサイズを変更したとき:

import { Component, OnInit, NgZone } from '@angular/core'; 
import { MatchMediaService } from '../shared/services/match-media.service'; 
import { HomeMobileComponent } from './home-mobile.component'; 
import { HomeDesktopComponent } from './home-desktop.component'; 

@Component({ 
    moduleId: module.id, 
    selector: 'home.component', 
    templateUrl: 'home.component.html', 
    providers: [ MatchMediaService ], 
    directives: [ HomeMobileComponent, HomeDesktopComponent ] 
}) 
export class HomeComponent implements OnInit 
{ 
    IsMobile: Boolean = false; 
    IsDesktop: Boolean = false; 

    constructor(
     private matchMediaService: MatchMediaService, 
     private zone: NgZone   
    ) 
    { 
     //GET INITIAL VALUE BASED ON DEVICE WIDTHS AT TIME THE APP RENDERS 
     this.IsMobile = (this.matchMediaService.IsPhone() || this.matchMediaService.IsTablet()); 
     this.IsDesktop = (this.matchMediaService.IsDesktop()); 

     var that = this; 


     /*--------------------------------------------------- 
     TAP INTO LISTENERS FOR WHEN DEVICE WIDTH CHANGES 
     ---------------------------------------------------*/ 

     this.matchMediaService.OnPhone(
      function (mediaQueryList: MediaQueryList) 
      { 
       that.ShowMobile(); 
      } 
     ); 

     this.matchMediaService.OnTablet(
      function (mediaQueryList: MediaQueryList) 
      { 
       that.ShowMobile(); 
      } 
     ); 

     this.matchMediaService.OnDesktop(
      function (mediaQueryList: MediaQueryList) 
      { 
       that.ShowDesktop(); 
      } 
     ); 
    } 

    ngOnInit() 
    { 

    } 

    ShowMobile() 
    { 
     this.zone.run(() => 
     { // Change the property within the zone, CD will run after 
      this.IsMobile = true; 
      this.IsDesktop = false; 
     }); 
    } 

    ShowDesktop() 
    { 
     this.zone.run(() => 
     { // Change the property within the zone, CD will run after 
      this.IsMobile = false; 
      this.IsDesktop = true; 
     }); 
    } 
} 
<home-mobile *ngIf="(IsMobile)"></home-mobile> 
<home-desktop *ngIf="(IsDesktop)"></home-desktop> 

このアプローチは動作します。私はデバイスに応じて適切なコンポーネントを読み込むことができます。これは、デバイスにコンテンツ(コンテンツ、スタイル、機能など)をカスタマイズし、最高のユーザーエクスペリエンスを可能にする機能を私に提供します。これにより、モバイル、タブレット、デスクトップのさまざまなコンポーネントをターゲットにすることもできます(ただし、モバイルとデスクトップの例のみに焦点を当てています)。

これを行うより良い方法はありますか?欠点は、すべてのコンポーネントを親コンポーネントで構成して、MatchMediaService経由でロードする子コンポーネントを判断することです。これは完全な生産レベルのアプリケーションで動作するように拡張可能ですか?私はよりよいアプローチに関するあなたのフィードバックに非常に関心があります。あるいは、このアプローチが、完全な制作アプリケーションのために受け入れられ、スケーラブルであれば、非常に興味があります。フィードバックいただきありがとうございます。

答えて

2

カスタムメディア対応の*ngIfまたは*ngSwitch構造ディレクティブを作成して、反復回数を少なくすることができます。

https://angular.io/docs/ts/latest/guide/structural-directives.html

+1

モバイルデバイスを検出するために、任意の場所にユーザーエージェント文字列「モビ」を探してお勧めします、この設計は、デスクトップコンポーネントおよびモバイルコンポーネントがその同じビルドに住むようになります未使用のコードを持つ大きなバンドルを意味します。あなたはそれが使用されているようにそれを揺るがすことはできませんが、実際には使用されません。 たとえば、「」は決してデスクトップ上で実行されませんか? –

+0

返事をありがとう。私は、あなたが提供したURLの中のメディア認識構造ディレクティブに関して特定のものを見つけることができませんでした。私は子コンポーネントをロードするためのngIf構造ディレクティブを使用しており、ngIfの決定ポイントを提供するメディア・アスペクトに対してMatchMediaServiceを使用しています。私は何が欠けていますか? –

+1

良いアイデアはありますか? Angularチームはすぐに使えるものを提供したいと思っていますが、良いアプローチを思いつくことはできませんでした。 '@View()'はここで助けられるはずだったが、うまくいかなかったので削除された。 –

-1

あなたは怠惰すなわち、モジュールをロードするためにルーティングすることにより、すべてのそのロジックを避けることができませんでした。 app.componentをnavigator.userAgentに基づいて対応するモジュールのルートにナビゲートさせることによって、モバイル、デスクトップ、 https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent

から、我々はトムが

https://embed.plnkr.co/NLbyBEbNoWd9SUW7TJFS/

関連する問題