1. ホーム
  2. angularjs

[解決済み] $location/html5とhashbangモードの切り替え/リンクのリライト

2022-04-29 22:27:26

質問

Angularは、tempaltes内のアンカータグのhref属性に表示されるURLを、html5モードでもhashbangモードでも動作するように書き換えてくれるという印象を受けました。そのため ロケーションサービスのドキュメント は、HTML Link Rewritingがハッシュバングの状況に対応すると言っているようです。 したがって、HTML5モードでないときはハッシュが挿入され、HTML5モードではハッシュが挿入されないと予想されます。

しかし、書き換えは行われていないようです。 以下の例では、モードを変更するだけではダメなのです。 アプリケーション内のすべてのリンクを手作業で書き換える必要があります(または、実行時に変数から派生させる。 モードに応じて、すべてのURLを手動で書き換える必要があるのでしょうか?

Angular 1.0.6, 1.1.4, 1.1.3 では、クライアントサイドのurl書き換えは行われていないようですね。 すべてのhref値の前に、hashbangモードでは#/を、html5モードでは/を付ける必要があるようです。

書き換えを発生させるために必要な設定はあるのでしょうか?私がドキュメントを読み間違えているのでしょうか?何か他の愚かなことをしているのでしょうか?

以下は小さな例です。

<head>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.3/angular.js"></script>
</head>

<body>
    <div ng-view></div>
    <script>
        angular.module('sample', [])
            .config(
        ['$routeProvider', '$locationProvider',
            function ($routeProvider, $locationProvider) {

                //commenting out this line (switching to hashbang mode) breaks the app
                //-- unless # is added to the templates
                $locationProvider.html5Mode(true);

                $routeProvider.when('/', {
                    template: 'this is home. go to <a href="/about"/>about</a>'
                });
                $routeProvider.when('/about', {
                    template: 'this is about. go to <a href="/"/>home</a'
                });
            }
        ])
            .run();
    </script>
</body>

追記:質問を読み返してみると、私は「リライト」という言葉を、誰が、いつリライトをしたいのか、十分に明確でないまま使っていたようです。質問は、「どのようにすれば アンギュラー をレンダリングするときに URL を書き換える方法と、JS コード内のパスを 2 つのモードで統一的に解釈する方法について説明します。 それは ではなく WebサーバーにHTML5互換のリクエストの書き換えをさせる方法についてです。

解決するには?

AngularJSのルーティングについては、ドキュメントがあまり明確ではありません。HashbangとHTML5モードについて書かれています。実際には、AngularJSのルーティングは3つのモードで動作します。

  • Hashbangモード
  • HTML5モード
  • HTML5モードでのハッシュバン

各モードには、それぞれのLocationUrlクラスがあります(LocationHashbangUrl、LocationUrl、LocationHashbangInHTML5Url)。

URLの書き換えをシミュレートするには、実際にhtml5modeをtrueに設定し、$snifferクラスを以下のように装飾する必要があります。

$provide.decorator('$sniffer', function($delegate) {
  $delegate.history = false;
  return $delegate;
});

これから詳しく説明します。

ハッシュバンモード

コンフィギュレーションです。

$routeProvider
  .when('/path', {
    templateUrl: 'path.html',
});
$locationProvider
  .html5Mode(false)
  .hashPrefix('!');

のように、HTMLファイル内でハッシュ付きURLを使用する必要がある場合です。

<a href="index.html#!/path">link</a>

ブラウザでは、以下のLinkを使用する必要があります。 http://www.example.com/base/index.html#!/base/path

純粋な Hashbang モードでは、HTML ファイル内のすべてのリンクは "index.html#!" のようにベースから始まる必要があることがお分かりいただけると思います。

HTML5モード

コンフィギュレーションです。

$routeProvider
  .when('/path', {
    templateUrl: 'path.html',
  });
$locationProvider
  .html5Mode(true);

HTMLファイルでベースを設定する必要があります。

<html>
  <head>
    <base href="/">
  </head>
</html>

このモードでは、HTMLファイル内で#を含まないリンクを使用することができます。

<a href="/path">link</a>

ブラウザでリンクします。

http://www.example.com/base/path

HTML5モードでのHashbang

このモードは、実際にHTML5モードを使用する際に、互換性のないブラウザで使用する場合に有効です。互換性のあるブラウザでこのモードをシミュレートするには、$snifferサービスをデコレートし、historyをfalseに設定することで可能です。

設定を行います。

$provide.decorator('$sniffer', function($delegate) {
  $delegate.history = false;
  return $delegate;
});
$routeProvider
  .when('/path', {
    templateUrl: 'path.html',
  });
$locationProvider
  .html5Mode(true)
  .hashPrefix('!');

HTML-fileにbaseを設定する。

<html>
  <head>
    <base href="/">
  </head>
</html>

この場合、HTMLファイルにハッシュを付けずにリンクを書くこともできます。

<a href="/path">link</a>

ブラウザでリンクします。

http://www.example.com/index.html#!/base/path