comment faire réactif composants dans Angular2
Je suis à gué sur mon chemin Angular2. Mon objectif est de créer un réactif application qui charge les différents composants en réponse à différents media-queries pour appareil largeurs. Mon exemple de travail a un 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);
}
});
}
};
}
Puis à l'intérieur d'un "parent" composant (HomeComponent), j'utilise MatchMediaService pour déterminer quel composant enfant (HomeMobileComponent ou HomeDesktopComponent) à charge en fonction de ce que MatchMediaService renvoie aussi bien en tant qu'auditeur des événements déclenchés lorsque le navigateur est redimensionnée par le biais de différentes dimensions:
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>
Cette approche fonctionne. Je peux charger le composant approprié en réponse à l'appareil. Il m'offre la possibilité de personnaliser un composant (contenu, style, fonctionnalité, etc) à l'appareil, permettant ainsi la meilleure expérience utilisateur. Cela aussi m'offre la possibilité de cibler des différents composants pour Mobile, Tablette et ordinateur de Bureau (bien que je ne me concentre sur mobile et ordinateur de bureau par exemple).
Est-il une meilleure façon de le faire? L'inconvénient, c'est que je suis obligeant chaque composant comporte le composant parent pour déterminer via MatchMediaService qui composant enfant à charge. Cela sera évolutive pour travailler dans une pleine soufflé niveau de production de l'app? Je suis très intéressé par vos commentaires sur une meilleure approche, ou si cette approche est acceptable et évolutive pour une pleine soufflé à la production de l'app. Merci pour vous commentaires.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez créer un support personnalisé-conscient
*ngIf
ou*ngSwitch
structurels directive pour la rendre moins répétitif.https://angular.io/docs/ts/latest/guide/structural-directives.html
<home-mobile>
ne sera jamais exécuté sur le bureau, à droite?@View()
était censé aider ici, mais a été abandonné car il n'a pas fonctionné.*ngIf
ou*ngSwitch
comme*meadiaSwitch
qui ajoute de la partie qui correspond à la largeur (ou autre). Le lien n'est censé montrer comment créer structurels directives.require.diverge({mobile: './[mobile].my-comp.template.html', desktop: './[desktop].my-comp.template.html')
. Cela fonctionne aussi pour les fichiers CSS et JS. Cependant, dans NG2 l'exécution du compilateur pourrait ne pas être là, donc, cette approche nécessite d'inspectionNe pourrait-on pas éviter de tout ce que la logique de routage paresseusement les modules chargés, c'est à dire. mobile, ordinateur de bureau, que ce soit, en faisant application.composant accédez au module correspondant de l'itinéraire en fonction de navigateur.userAgent? De https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
nous vous recommandons de recherche de la chaîne “Mobi” n'importe où dans l'Agent Utilisateur à détecter un appareil mobile
https://embed.plnkr.co/NLbyBEbNoWd9SUW7TJFS/