18

Tôi đang lội theo hướng của mình vào Angular2. Mục tiêu của tôi là tạo ứng dụng đáp ứng tải các thành phần khác nhau để phản hồi các truy vấn phương tiện khác nhau cho chiều rộng thiết bị. Ví dụ làm việc của tôi có một MatchMediaService:cách làm các thành phần đáp ứng trong 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); 
       } 
      }); 
     } 
    }; 
} 

Sau đó bên trong một 'mẹ' thành phần (HomeComponent), tôi sử dụng MatchMediaService để xác định thành phần con (HomeMobileComponent hoặc HomeDesktopComponent) để tải tùy thuộc vào những gì MatchMediaService trả cũng như các sự kiện người nghe rằng lửa khi trình duyệt thay đổi kích thước thông qua kích thước khác nhau:

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> 

cách tiếp cận này hoạt động. Tôi có thể tải thành phần thích hợp để đáp ứng với thiết bị. Nó cho tôi khả năng tùy chỉnh một thành phần (nội dung, kiểu dáng, chức năng, vv) cho thiết bị, do đó cho phép trải nghiệm người dùng tốt nhất. Điều này cũng cho tôi khả năng nhắm mục tiêu các thành phần khác nhau cho Thiết bị di động, Máy tính bảng và Máy tính để bàn (mặc dù tôi chỉ tập trung vào thiết bị di động và máy tính để bàn chẳng hạn).

Có cách nào tốt hơn để thực hiện việc này không? Nhược điểm là tôi buộc tất cả các thành phần phải bao gồm thành phần cha mẹ để xác định thông qua MatchMediaService mà thành phần con để tải. Điều này có thể mở rộng để làm việc trong một ứng dụng cấp sản xuất thổi đầy đủ? Tôi rất quan tâm đến phản hồi của bạn về cách tiếp cận tốt hơn hoặc nếu phương pháp này có thể chấp nhận được và có thể mở rộng cho ứng dụng sản xuất toàn diện. Cảm ơn bạn đã phản hồi.

Trả lời

2

Bạn có thể tạo chỉ thị cấu trúc tùy chỉnh nhận biết *ngIf hoặc *ngSwitch để làm cho nó ít lặp đi lặp lại.

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

+1

Tom, thiết kế này sẽ làm cho các thành phần máy tính để bàn và linh kiện điện thoại di động sống trong cùng xây dựng mà có nghĩa là một gói lớn có mã không sử dụng. Bạn sẽ không thể lắc cây như nó được sử dụng, nhưng không thực sự được sử dụng. Ví dụ: '' sẽ không bao giờ chạy trên máy tính để bàn, phải không? –

+0

Cảm ơn bạn đã trả lời. Tôi không thể tìm thấy bất kỳ điều gì cụ thể liên quan đến chỉ thị cấu trúc truyền thông nhận biết trong URL bạn đã cung cấp. Tôi đang sử dụng ngIf chỉ thị cấu trúc để tải thành phần con và sử dụng MatchMediaService cho khía cạnh phương tiện truyền thông cung cấp điểm quyết định cho ngIf. Tôi đang thiếu gì? –

+1

Bạn có ý tưởng nào tốt hơn không? Có vẻ như nhóm Angular muốn cung cấp một cái gì đó ngoài hộp nhưng không thể đưa ra một số cách tiếp cận tốt. '@View()' được cho là sẽ trợ giúp ở đây nhưng bị loại bỏ vì nó không hoạt động. –

-1

Không thể bạn tránh được tất cả lôgic bằng cách định tuyến để lười biếng nạp mô-đun, tức là. điện thoại di động, máy tính để bàn, bất cứ điều gì, bằng cách làm cho app.component điều hướng đến tuyến đường của mô-đun tương ứng dựa trên navigator.userAgent? Từ https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent

chúng tôi khuyên bạn nên tìm kiếm chuỗi “Mobi” bất cứ nơi nào trong User Agent để phát hiện một thiết bị di động

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

Các vấn đề liên quan