Ответ 1
Вы можете создать собственную конструктивную директиву *ngIf
или *ngSwitch
, ориентированную на носители, чтобы сделать ее менее повторяющейся.
https://angular.io/docs/ts/latest/guide/structural-directives.html
Я пробираюсь в 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, какой дочерний компонент загрузить. Будет ли это масштабируемо работать в полномасштабном приложении уровня производительности? Я очень заинтересован в ваших отзывах о лучшем подходе, или если этот подход приемлем и масштабируется для полнофункционального приложения для производства. Спасибо за отзыв.
Вы можете создать собственную конструктивную директиву *ngIf
или *ngSwitch
, ориентированную на носители, чтобы сделать ее менее повторяющейся.
https://angular.io/docs/ts/latest/guide/structural-directives.html
Нельзя ли избежать этой логики путем маршрутизации на лениво загружаемые модули, т.е. мобильный, рабочий стол, независимо от того, чтобы app.component перешел на соответствующий маршрут модуля на основе navigator.userAgent? Из https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
мы рекомендуем искать строку "Mobi" в любом месте User Agent для обнаружения мобильного устройства.