18

में उत्तरदायी घटकों को कैसे करें I Angular2 में अपना रास्ता छीन रहा हूं। मेरा उद्देश्य एक उत्तरदायी ऐप बनाना है जो डिवाइस की चौड़ाई के लिए विभिन्न मीडिया-क्वेरी के जवाब में विभिन्न घटकों को लोड करता है। मेरे काम कर उदाहरण एक MatchMediaService है: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); 
       } 
      }); 
     } 
    }; 
} 
फिर एक 'जनक' घटक (HomeComponent) के अंदर

, मैं MatchMediaService का उपयोग जो बच्चे घटक (HomeMobileComponent या HomeDesktopComponent) निर्धारित करने के लिए क्या 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> 

यह दृष्टिकोण काम करता है। मैं डिवाइस के जवाब में उचित घटक लोड कर सकता हूं। यह मुझे डिवाइस पर एक घटक (सामग्री, शैली, कार्यक्षमता, आदि) को अनुकूलित करने की क्षमता प्रदान करता है जिससे इस प्रकार सर्वोत्तम उपयोगकर्ता अनुभव सक्षम हो जाता है। यह मुझे मोबाइल, टैबलेट और डेस्कटॉप के लिए विभिन्न घटकों को लक्षित करने की क्षमता भी प्रदान करता है (हालांकि मैं केवल मोबाइल और डेस्कटॉप पर ध्यान केंद्रित कर रहा हूं)।

क्या ऐसा करने का कोई बेहतर तरीका है? नकारात्मकता यह है कि मैं प्रत्येक घटक को माता-पिता घटक से शामिल करने के लिए मजबूर कर रहा हूं ताकि मैचमेडिया सेवा के माध्यम से निर्धारित किया जा सके जो कि बाल घटक लोड हो। क्या यह एक पूर्ण उड़ा उत्पादन स्तर ऐप में काम करने के लिए स्केलेबल होगा? मुझे बेहतर प्रतिक्रिया पर आपकी प्रतिक्रिया में बहुत दिलचस्पी है, या यदि यह दृष्टिकोण एक पूर्ण उड़ा उत्पादन ऐप के लिए स्वीकार्य और स्केलेबल है। आपके लिए प्रतिक्रिया के लिए धन्यवाद।

उत्तर

2

आप इसे कम से कम दोहराए जाने के लिए एक कस्टम मीडिया-जागरूक *ngIf या *ngSwitch संरचनात्मक निर्देश बना सकते हैं।

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

+1

टॉम पता लगाने के लिए स्ट्रिंग "Mobi" उपयोगकर्ता एजेंट में कहीं भी के लिए देखने की सलाह देते, इस डिजाइन और मोबाइल घटकों डेस्कटॉप घटकों कर देगा ही निर्माण में रहते हैं जो का मतलब है एक बड़ा बंडल जिसमें अप्रयुक्त कोड है। आप इसे इस्तेमाल करने के रूप में पेड़-शेक करने में सक्षम नहीं होंगे, लेकिन वास्तव में उपयोग नहीं किया जाता है। उदाहरण के लिए, '' डेस्कटॉप पर कभी नहीं चलाएगा, है ना? –

+0

उत्तर के लिए धन्यवाद। आपके द्वारा प्रदान किए गए यूआरएल में मीडिया जागरूक संरचनात्मक निर्देशों के बारे में मुझे कुछ भी विशिष्ट नहीं मिला। मैं ngIf के लिए निर्णय बिंदु प्रदान करने वाले मीडिया पहलू के लिए बाल घटक लोड करने और MatchMediaService का उपयोग करने के लिए ngIf संरचनात्मक निर्देश का उपयोग कर रहा हूं। मैं क्या खो रहा हूँ? –

+1

क्या आपके पास बेहतर विचार है? ऐसा लगता है कि कोणीय टीम कुछ आउट ऑफ़ द बॉक्स प्रदान करना चाहता है लेकिन कुछ अच्छे दृष्टिकोण के साथ नहीं आ सकती थी। '@ व्यू()' यहां मदद करने के लिए माना जाता था लेकिन गिरा दिया गया क्योंकि यह काम नहीं कर सका। –

-1

आप lazily लोड करने के लिए मॉड्यूल, यानी रूट करके सब उस तर्क से बचने नहीं कर सका। मोबाइल, डेस्कटॉप, जो भी, app.component को navigator.userAgent के आधार पर संबंधित मॉड्यूल के रूट पर नेविगेट करके? https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent

से हम एक मोबाइल डिवाइस

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