我正在闯入Angular2.我的目标是创建一个响应应用程序,加载不同的组件以响应不同的设备宽度的媒体查询.我的工作示例有一个MatchMediaService:
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来确定要根据MatchMediaService返回的哪个子组件(HomeMobileComponent或HomeDesktopComponent)以及浏览器通过不同维度调整大小时触发的侦听器事件:
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来确定要加载的子组件.这是否可以扩展到一个完整的生产级应用程序?我对一个更好的方法的反馈非常感兴趣,或者这种方法对于一个完整的生产应用程序是可以接受和可扩展的.感谢您的反馈.
您可以创建自定义的媒体感知* ngIf或* ngSwitch结构指令,使其不太重复.
https://angular.io/docs/ts/latest/guide/structural-directives.html