web-dev-qa-db-ja.com

$ location / html5とhashbangモードの切り替え/リンクの書き換え

私はAngularがテンプレート内のアンカータグのhref属性に現れるURLを書き換えて、それらがhtml5モードであろうとhashbangモードであろうとうまくいくだろうという印象を受けました。 位置情報サービスのドキュメンテーション は、HTML Link Rewritingがhashbangの状況を処理すると言っているようです。したがって、HTML 5モードではない場合はハッシュが挿入され、HTML 5モードではそうではないと予想されます。

しかし、書き換えは行われていないようです。次の例では、モードを変更することはできません。アプリケーション内のすべてのリンクを手動で書き換える(または実行時に変数から取得する)必要があります。モードによっては、すべての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を書き換えるAngularの取得方法と、JSコード内のパスを2つのパスで一様に解釈する方法を取得することです。モードWebサーバーにHTML5互換の要求の書き換えを行わせる方法についてはできません

177
laurelnaiad

ドキュメントはAngularJSルーティングについてはあまり明確ではありません。 HashbangとHTML 5モードについて話しています。実際、Angular JSルーティングは3つのモードで動作します。

  • ハッシュバングモード
  • HTML 5モード
  • HTML5モードのHashbang

各モードには、それぞれ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>

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

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

HTML 5モード

構成:

$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ファイルにベースを設定します。

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

この場合、リンクはHTMLファイルにハッシュなしで書くこともできます。

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

ブラウザでリンク:

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

将来の読者の方々、Angular 1.6を使っているのなら、hashPrefixも変更する必要があります。

appModule.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix('');
}]);

あなたのHTMLのベースを設定することを忘れないでください<head>

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

変更履歴に関する詳細 here

7
Mistalis

私は、HTML5モードと固定トークンを使って自分のアプリケーションにアクセスしてからhashbangメソッドに切り替えることができるようにしたい(ユーザーが自分のページを更新できるようにトークンを保持するため)。

私のアプリにアクセスするためのURL:

http://myapp.com/amazing_url?token=super_token

それからユーザーがページをロードするとき:

http://myapp.com/amazing_url?token=super_token#/amazing_url

その後、ユーザーが移動したとき:

http://myapp.com/amazing_url?token=super_token#/another_url

これにより、トークンをURLに保持し、ユーザーが閲覧しているときの状態を保持します。 URLが少し見えなくなりましたが、それを実行するための完璧な方法はありません。

HTML5モードを有効にしてからこのコントローラを追加しないでください。

.config ($stateProvider)->
    $stateProvider.state('home-loading', {
         url: '/',
         controller: 'homeController'
    })
.controller 'homeController', ($state, $location)->
    if window.location.pathname != '/'
        $location.url(window.location.pathname+window.location.search).replace()
    else
        $state.go('home', {}, { location: 'replace' })
0
Luc Boissaye

これは私が理解するのにしばらく時間がかかったので私はそれがどのように働いていたかです - Angular WebAPI ASP SEOのための#なしのルーティング

  1. index.htmlに追加 - base href = "/">
  2. $ locationProvider.html5Mode(true)を追加してください。 app.configに

  3. 私は画像をアップロードするために無視される特定のコントローラ(これはホームコントローラにあった)を必要としたので、そのルールをRouteConfigに追加しました

         routes.MapRoute(
            name: "Default2",
            url: "Home/{*.}",
            defaults: new { controller = "Home", action = "SaveImage" }
        );
    
  4. Global.asaxに以下を追加してください - apiと画像のアップロードパスを無視することを確実にすることはそれらが通常のように機能するようにさせます。

     private const string ROOT_DOCUMENT = "/Index.html";
    
    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        var path = Request.Url.AbsolutePath;
        var isApi = path.StartsWith("/api", StringComparison.InvariantCultureIgnoreCase);
        var isImageUpload = path.StartsWith("/home", StringComparison.InvariantCultureIgnoreCase);
    
        if (isApi || isImageUpload)
            return;
    
        string url = Request.Url.LocalPath;
        if (!System.IO.File.Exists(Context.Server.MapPath(url)))
            Context.RewritePath(ROOT_DOCUMENT);
    }
    
  5. リダイレクトするには、window.location ...ではなく$ location.url( '/ XXX')を使用してください。

  6. 絶対パスでCSSファイルを参照する

ではなく

<link href="app/content/bootstrapwc.css" rel="stylesheet" />

最後の注意 - この方法でそれを行うことで私は完全に制御できるようになり、Web設定に何もする必要はありませんでした。

理解するのにしばらく時間がかかったので、これが役立つことを願っています。

0
tfa