Я пробираюсь в 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 для определения того, какой дочерний компонент (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>
Этот подход работает. Я могу загрузить соответствующий компонент в ответ на устройство. Это дает мне возможность настраивать компонент (контент, стиль, функциональность и т.д.) На устройство, что позволяет наилучшим образом работать с пользователями. Это также дает мне возможность настраивать таргетинг на различные компоненты для мобильных устройств, планшетных компьютеров и настольных компьютеров (хотя в основном я ориентируюсь только на мобильные и настольные компьютеры).
Есть ли лучший способ сделать это? Недостатком является то, что я заставляю каждый компонент состоять из родительского компонента, чтобы определить через MatchMediaService, какой дочерний компонент загрузить. Будет ли это масштабируемо работать в полномасштабном приложении уровня производительности? Я очень заинтересован в ваших отзывах о лучшем подходе, или если этот подход приемлем и масштабируется для полнофункционального приложения для производства. Спасибо за отзыв.