Question Le mode AngularJS HTML5 se dégrade en plein page en remplacement du hashbang


En activant le mode HTML5 dans AngularJS, le $location Le service réécrira les URL pour en supprimer le hashbang. C'est une fonctionnalité géniale qui m'aidera avec mon application, mais il y a un problème avec son retour au mode hashbang. Mon service requiert une authentification et je suis obligé d'utiliser un mécanisme d'authentification externe à partir de mon application. Si un utilisateur tente d'accéder à une URL contenant mon hashbang, il le redirigera d'abord vers la page d'authentification (il ne touchera jamais mon service sans une authentification réussie), puis le redirigera vers mon application. Étant donné que le mot-clé de hachage est uniquement visible du côté client, il sera déposé quelles que soient les parties de l'itinéraire qui suivront au moment où elles atteindront mon serveur. Une fois qu'ils sont authentifiés, ils peuvent ressaisir l'URL et cela fonctionnera, mais c'est cette première fois qui causera une interruption de l'expérience utilisateur.

Ma question est alors, y a-t-il un moyen de passer de $location.html5Mode(true) au repli des rechargements de pages complets pour les navigateurs non compatibles, en ignorant la méthode de routage de hashbang entièrement dans AngularJS?

La meilleure comparaison des implémentations disponibles de ce que je vise serait quelque chose comme la navigation dans les dossiers sur github.com. Si le navigateur prend en charge la réécriture de l'URL sans lancer d'actualisation de la page, la page charge les pièces nécessaires de manière asynchrone. Si le navigateur ne le prend pas en charge, lorsqu'un utilisateur clique sur un dossier, une actualisation complète de la page se produit. Est-ce que cela peut être réalisé avec AngularJS au lieu d'utiliser le mode hashbang?


22
2018-02-19 22:29


origine


Réponses:


NE PAS écraser la fonctionnalité principale.

Utilisez Modernizr, faites la détection des fonctionnalités, puis procédez en conséquence.

vérifier la prise en charge de l'historique de l'API

if (Modernizr.history) {
  // history management works!
} else {
  // no history support :(
  // fall back to a scripted solution like History.js
}

2
2017-09-22 07:06



Essayez d'envelopper la configuration $ location et $ routeProvider dans la vérification de l'API HTML5 History du navigateur, comme ceci:

if (isBrowserSupportsHistoryAPI()) {
    $location.html5Mode(true)
    $routeProvider.when(...);
}

Vous pouvez également avoir besoin de créer un wrapper à $ location si vous l'utilisez pour changer de chemin. (Désolé pour terrible anglais)


1
2018-03-28 12:24



Pourquoi ne pas gérer la redirection non authentifiée du côté client pour cette situation? Je devrais en savoir un peu plus sur le fonctionnement de votre application pour vous proposer une solution plus spécifique, mais essentiellement quelque chose comme:

  1. L'utilisateur accède à une route gérée par AngularJS, le serveur héberge le modèle principal et le javascript AngularJS
  2. L'utilisateur n'est pas authentifié, AngularJS le détecte et redirige vers la page d'authentification

Vous pourriez avoir quelque chose dans le bloc d'exécution du module lorsque l'application AngularJS démarre:

module('app',[])
  .configure(...yadda...yadda...yadda...)
  .run(['$location', 'authenticationService', function($location, auth) {
    if (!auth.isAuthenticated()) {
      $location.url(authenticationUrl) 
    }
  });

Je suis passé dans un service qui trouverait si vous aviez été authentifié, à vous de voir comment, pourrait vérifier un cookie de session, pourrait toucher votre API pour demander. Cela dépend vraiment de la manière dont vous souhaitez continuer à vérifier l'authentification à mesure que l'application client s'exécute.


1
2017-09-30 20:15



Vous pouvez essayer de remplacer la fonctionnalité du service $ location. L'idée générale serait de réécrire l'URL selon que quelqu'un est déjà authentifié ou non, ou simplement d'utiliser une seule approche (sans hashbangs) pour toutes les URL, que html5mode soit activé ou non.

Je ne suis pas sûr de bien comprendre le cas d'utilisation pour que je ne puisse pas écrire le code exact dont vous avez besoin. Voici un exemple d'implémentation de la manière de remplacer / implémenter et d'enregistrer le service $ location, en s'assurant que le hashbang est toujours éliminé:

app.service('$location', [function() {
    var DEFAULT_PORTS = {
        ftp: 21,
        http: 80,
        https: 443
    };

    angular.extend(this, {
        absUrl: function() {
            return location.href;
        },
        hash: function(hash) {
            return location.hash.substr(1);
        },
        host: function() {
            return location.host;
        },
        path: function(path) {
            if (!path) {
                return location.pathname;
            }
            location.pathname = path;
            return this;
        },
        port: function() {
            return location.port ? Number(location.port) : DEFAULT_PORTS[this.protocol()] || null;
        },
        protocol: function() {
            return location.protocol.substr(0, location.protocol.length - 1);
        },
        replace: function() {
            return this;
        },
        search: function(search, paramValue) {
            if (search || paramValue) {
                return this;
            }
            var query = {};
            location.search.substr(1).split("&").forEach(function(pair) {
                pair = pair.split("="); query[pair[0]] = decodeURIComponent(pair[1]);
            });
            return query;
        },
        url: function(url, replace) {
            return this.path();
        }
    });
}]);

1
2018-06-09 22:21