18

Angular2'ye gidiyorum. Amacım, cihaz genişlikleri için farklı medya sorgularına yanıt olarak farklı bileşenleri yükleyen duyarlı bir uygulama oluşturmaktır. Ben MatchMediaService dinleyici etkinliklerin yanı sıra döner şeye bağlı olarak yüklemek için hangi çocuk bileşenini (HomeMobileComponent veya HomeDesktopComponent) belirlemek üzere MatchMediaService kullandıkları 'ebeveyn' bileşeni (HomeComponent) içindeki SonraDuyarlı bileşenleri nasıl yapılacağını 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); 
       } 
      }); 
     } 
    }; 
} 

: My çalışan örnek MatchMediaService vardır tarayıcı farklı boyutlara yoluyla boyutlandırır yangın:

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> 

Bu yaklaşım çalışır. Cihaza tepki olarak uygun bileşeni yükleyebilirim. Bana, bir bileşenin (içerik, stil, işlevsellik vb.) Cihaza uyarlanabilmesi ve böylece en iyi kullanıcı deneyimini sağlayabilmem için bana imkan verir. Bu ayrıca, Mobil, Tablet ve Masaüstü için farklı bileşenleri hedefleme yeteneğini de sağlıyor (ancak, örneğin, yalnızca mobil ve masaüstüne odaklanıyorum).

Bunu yapmanın daha iyi bir yolu var mı? Dezavantajı, hangi bileşeninin yükleneceği MatchMediaService aracılığıyla belirlemek için her bileşenin ana bileşenden oluşmasını zorluyorum. Bu tam bir şişirilmiş üretim düzeyinde uygulamada çalışmak için ölçeklenebilir mi? Daha iyi bir yaklaşımla ilgili görüşlerinizle çok ilgileniyorum veya bu yaklaşım kabul edilebilir ve tam kapsamlı bir üretim uygulaması için ölçeklendirilebilirse. Geri bildiriminiz için teşekkürler.

cevap

2

Daha az tekrarlı olması için medyaya duyarlı *ngIf veya *ngSwitch yapısal yönergesi oluşturabilirsiniz.

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

+1

Tom algılamak için dize her yerde Kullanıcı Agent “Mobi” arayan tavsiye, bu masaüstü bileşenleri yapacak tasarım ve mobil bileşenler aynı yapı içinde yaşadığımız kullanılmayan kodu olan büyük bir paket demektir. Kullandığı gibi ağaç sallayamayacaksınız, ama gerçekten kullanılmıyor. Örneğin, "" masaüstü üzerinde asla çalışmayacak, değil mi? –

+0

Cevabınız için teşekkürler. Sağladığınız URL’deki medyayla ilgili yapısal direktiflerle ilgili belirli bir şey bulamadım. Çocuk bileşenini yüklemek için ngIf yapısal yönergesi kullanıyorum ve ngIf için karar noktasını sağlayan ortam boyutu için MatchMediaService kullanıyorum. Neyi kaçırıyorum? –

+1

Daha iyi bir fikrin var mı? Angular ekibi, kutudan çıkmış bir şey sağlamak istiyor ama iyi bir yaklaşımla gelemedi. '@View()' ın burada yardımcı olması gerekiyordu ama işe yaramadığı için düştü. –