$ location / html5 ve hashbang modu / bağlantı yeniden yazma arasında geçiş yapma


179

Angular, bağlantı etiketlerinin href özniteliklerinde tempaltes içinde görünen URL'leri yeniden yazacağı, html5 veya hashbang modunda çalışacakları izlenimi altındaydım. Konum hizmeti için dokümantasyon HTML Link Yeniden Yazma hashbang durumun ilgilenir söylemek gibi görünüyor. Böylece HTML5 modunda değil, karma ekleneceğini ve HTML5 modunda, onlar olacağını beklemem.

Ancak, yeniden yazma gerçekleşmiyor gibi görünüyor. Aşağıdaki örnek sadece modu değiştirmeme izin vermiyor. Uygulamadaki tüm bağlantıların elle yeniden yazılması gerekir (veya çalışma zamanında bir değişkenten türetilir. Moda bağlı olarak tüm URL'leri manuel olarak yeniden yazmam gerekir mi?

Açısal 1.0.6, 1.1.4 veya 1.1.3'te herhangi bir istemci tarafı url yeniden yazma işlemi görmüyorum. Tüm href değerlerinin # / hashbang modu ve / html5 modu için başına eklenmesi gerektiği anlaşılıyor.

Yeniden yazmaya neden olacak bazı yapılandırmalar var mı? Belgeleri yanlış mı okuyorum? Aptalca bir şey mi yapıyorsun?

İşte küçük bir örnek:

<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="https://stackoverflow.com/about"/>about</a>'
                });
                $routeProvider.when('/about', {
                    template: 'this is about. go to <a href="https://stackoverflow.com/"/>home</a'
                });
            }
        ])
            .run();
    </script>
</body>

Zeyilname: sorumu yeniden okurken, yeniden yazmayı kim ve ne zaman yapmak istediğime dair netlik olmadan "yeniden yazma" terimini kullandığımı görüyorum. Soru nasıl hakkındadır Eğik o yolları oluşturur ve bu iki mod arasında eşit olarak JS kodu yolları yorumlama nasıl ne zaman URL'leri yeniden yazmak için. Bu, bir web sunucusunun isteklerin HTML5 uyumlu yeniden yazılmasını sağlamasıyla ilgili değildir .


1
İşte çözüm için açısal 1.6 .
17'de Mistalis

Yanıtlar:


361

Belgeler AngularJS yönlendirmesi hakkında çok net değil. Hashbang ve HTML5 modundan bahsediyor. Aslında, AngularJS yönlendirme üç modda çalışır:

  • Hashbang Modu
  • HTML5 Modu
  • HTML5 Modunda Hashbang

Her mod için ilgili bir LocationUrl sınıfı vardır (LocationHashbangUrl, LocationUrl ve LocationHashbangInHTML5Url).

URL yeniden yazmayı simüle etmek için html5mode öğesini true olarak ayarlamanız ve $ sniffer sınıfını aşağıdaki gibi dekore etmeniz gerekir:

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

Şimdi bunu daha ayrıntılı olarak açıklayacağım:

Hashbang Modu

Yapılandırma:

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

Bu, HTML dosyalarınızdaki gibi karma içeren URL'leri kullanmanız gerektiği durumdur.

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

Tarayıcıda aşağıdaki Bağlantıyı kullanmalısınız: http://www.example.com/base/index.html#!/base/path

Saf Hashbang modunda görebileceğiniz gibi, HTML dosyalarındaki tüm bağlantılar "index.html #!" Gibi bir tabanla başlamalıdır.

HTML5 Modu

Yapılandırma:

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

Tabanı HTML dosyasında ayarlamalısınız

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

Bu modda, HTML dosyalarında # olmadan bağlantıları kullanabilirsiniz

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

Tarayıcıda Bağlantı:

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

HTML5 Modunda Hashbang

Bu mod, aslında HTML5 modunu kullandığımızda, ancak uyumsuz bir tarayıcıda etkinleştirilir. $ Sniffer hizmetini dekore ederek ve geçmişi false olarak ayarlayarak bu modu uyumlu bir tarayıcıda simüle edebiliriz.

Yapılandırma:

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

Tabanı HTML dosyasında ayarlayın:

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

Bu durumda, bağlantılar HTML dosyasında karma olmadan da yazılabilir

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

Tarayıcıda Bağlantı:

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

Detaylı açıklama için teşekkürler, jüpiter. Patlamayı atlayıp karma ve hile açısını moda bağlı olarak iki URL seti gerektirmeyecek şekilde tutamamaya bakacağım!
laurelnaiad

1
Sanırım problemini tam olarak anlamadım. Neden yalnızca karma olmayan URL'leri kullanmıyorsunuz? Geçmiş API'sını destekleyen tarayıcılarda ve geçmiş API'sını desteklemeyen tarayıcılarda çalışırlar. AngularJS, bağlantıların tıklamalarını engellerken geçmiş API'sını desteklemeyen tarayıcılarda üzerlerine tıkladığınızda # sürümünü konum çubuğuna koyacaktır.
jüpiter

Her iki modu da destekleyecek bir çerçeve üzerinde çalışıyorum. Uygulama yazarları, şablonlarında karma olup olmadığı ve / veya göreli yolların yorumlanmasında değişiklik olup olmadığı konusunda endişe duymadan birini veya diğerini seçebilmelidir. Umarım hileniz "yaptığınız tek şeyin modu değiştirmek olduğunu" doğru yapmasına yardımcı olacaktır (pratik çözüm "modu html5 olarak ayarlayın ve ardından tarayıcı özellikleri hakkında açısal olarak yalan söyleyin").
laurelnaiad

1
Ben alıyorum $providetanımsız?
Petrus Theron

1
@pate - dekoratörü kurarken yapılandırma işlevinize $ Prov enjekte etmeniz gerekir.
laurelnaiad

8

Gelecekte okuyanlar, eğer Angular 1.6 kullanıyorsanız , aşağıdakileri de değiştirmeniz gerekir hashPrefix:

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

HTML'nizdeki tabanı ayarlamayı unutmayın <head>:

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

Değişiklik günlüğü hakkında daha fazla bilgi here.


3
teşekkürler @Mistalis. cevabınız iyi çalışıyor. ancak yönlendirmeden sonra sayfayı yenilediğimde sorun oluştu, sayfa bulunamadı hataları oluşuyor. lütfen bana yardım et ..
Ashish Mehta

@AshishMehta Merhaba Ashish. Bu cevabı okumanızı tavsiye ederim , sorununuzu çözebilir. Hoşçakal! :)
Mistalis

0

SEO için # olmadan Açısal WebAPI ASP Yönlendirme

  1. Index.html'ye ekle - base href = "/">
  2. $ LocationProvider.html5Mode (true) öğesini ekleyin; app.config dosyasına

  3. Bu kuralı RouteConfig'e eklediğim için görüntüleri yüklemek için yok sayılmak üzere belirli bir denetleyiciye (ev denetleyicisindeydim) ihtiyacım vardı.

         routes.MapRoute(
            name: "Default2",
            url: "Home/{*.}",
            defaults: new { controller = "Home", action = "SaveImage" }
        );
  4. Global.asax'ta aşağıdakileri ekleyin - api ve resim yükleme yollarını yok saydığınızdan emin olun, normal şekilde çalışmasına izin verin, aksi takdirde diğer her şeyi yeniden yönlendirin.

     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. Yönlendirmek için window.location ... değil, $ location.url ('/ XXX') kullandığınızdan emin olun

  6. Mutlak yolla CSS dosyalarına başvuru

ve yok

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

Son not - bu şekilde yapmak bana tam kontrol verdi ve web yapılandırmasına hiçbir şey yapmam gerekmedi.

Umarım bu bana yardımcı olması için biraz zaman aldı.


0

HTML5 modu ve sabit bir belirteç ile benim uygulama erişmek ve daha sonra hashbang yöntemine (kullanıcı sayfasını yenilemek böylece belirteci tutmak için) geçmek mümkün istedim.

Uygulamama erişmek için URL:

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

Ardından kullanıcı sayfayı yüklediğinde:

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

Ardından kullanıcı navigasyon yaptığında:

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

Bununla jetonu URL'de saklıyorum ve kullanıcı göz atarken durumu koruyorum. URL'nin görünürlüğünü biraz kaybettim, ancak bunu yapmanın mükemmel bir yolu yok.

Bu yüzden HTML5 modunu etkinleştirmeyin ve ardından bu denetleyiciyi ekleyin:

.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' })
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.