Routing AngularJS bez skrótu „#”

223

Uczę się AngularJS i jest jedna rzecz, która naprawdę mnie denerwuje.

Używam $routeProviderdo deklarowania reguł routingu dla mojej aplikacji:

$routeProvider.when('/test', {
  controller: TestCtrl,
  templateUrl: 'views/test.html'
})
.otherwise({ redirectTo: '/test' });

ale kiedy przechodzę do mojej aplikacji w przeglądarce, widzę app/#/testzamiast app/test.

Więc moje pytanie brzmi: dlaczego AngularJS dodaje ten skrót #do adresów URL? Czy można tego uniknąć?

pikkvile
źródło
2
Oto rozwiązanie, jeśli używasz Angulara 1.6.
Mistalis

Odpowiedzi:

265

W rzeczywistości potrzebujesz # (hashtag) dla przeglądarek innych niż HTML5.

W przeciwnym razie po prostu wykonają połączenie HTTP z serwerem we wspomnianym href. # To stary skrót przeglądarki, który nie uruchamia żądania, co pozwala wielu frameworkom js zbudować własne przekierowanie po stronie klienta.

Możesz użyć, $locationProvider.html5Mode(true)aby powiedzieć angularowi, aby używał strategii HTML5, jeśli jest dostępna.

Oto lista przeglądarek obsługujących strategię HTML5: http://caniuse.com/#feat=history

plus-
źródło
4
Ok dziękuję. Podejrzewałem to. Ale jak dla mnie jest to dość nieprzyjazne dla użytkownika! Powiedzmy, że chcę, aby niektóre zasoby były dostępne za pośrednictwem adresu URL, aplikacji / res. Jak użytkownicy mojej witryny mogą dowiedzieć się, że zamiast tego powinni wpisać app / # / res?
pikkvile
5
Ale jeśli tak, to dlaczego te ścieżki muszą być widoczne na pasku lokalizacji? Jeśli użytkownicy nie będą ich używać, mogę po prostu stworzyć jednostronicową aplikację javascript.
pikkvile
6
Jest to przydatne, gdy chcesz śledzić stan aplikacji. Ramy oferują mechanizm historii. Dodatkowo pozwala na bezpośredni dostęp do stanu twojej aplikacji, na przykład poprzez udostępnianie adresów URL
plus
6
Hashtag nie jest wymagany w nowoczesnych przeglądarkach obsługujących interfejs API historii HTML5. Zobacz odpowiedź @ skeep i podane linki. W trybie HTML5 Angular będzie używać hashtagów tylko wtedy, gdy przeglądarka go nie obsługuje. Zauważ też, że nie musisz używać $ routeProvider, jeśli nie chcesz ... możesz połączyć własny routing za pomocą kliknięć ng i ng-include (w rzeczywistości musisz to zrobić, jeśli potrzebujesz wielu poziomów routing, ponieważ ng-view może pojawić się tylko raz na stronę). Zobacz także stackoverflow.com/questions/12793609/…
Mark Rajcok
2
Dla hashbang / pushState / server-side rendering html przypadku Twittera jest całkiem miło czytać engineering.twitter.com/2012/12/... Wyjaśnia, w jaki sposób udało im się to zrobić tak, że to wstecznie kompatybilne ze starej przeglądarki i wyszukiwania silniki. Wiem, że to nie jest specyficzne dla Angulara, ale możesz odtworzyć przepływ.
jackdbernier
47

Jeśli włączyłeś tryb html5, jak powiedzieli inni, i utwórz .htaccessplik z następującą zawartością (dostosuj do swoich potrzeb):

RewriteEngine   On
RewriteBase     /
RewriteCond     %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteCond     %{REQUEST_FILENAME} !-f
RewriteCond     %{REQUEST_FILENAME} !-d
RewriteRule     ./index.html [L]

Użytkownicy zostaną przekierowani do Twojej aplikacji, gdy podążą właściwą trasą, a aplikacja odczyta trasę i przeniesie ją na właściwą „stronę” w jej obrębie.

EDYCJA: Upewnij się, że nie ma konfliktu nazw plików lub katalogów z twoimi trasami.

niedźwiedź
źródło
czy jest to wersja nginx? gdy ładuję /aboutstronę, nie działa, chyba że przejdę do niej przez aplikację.
chovy
Nigdy ich nie używałem, ale spróbuj tego: stackoverflow.com/questions/5840497/convert-htaccess-to-nginx
bearfriend
3
@chovy - oto wersja nGinx: server {nazwa_serwera moja-aplikacja; root / path / to / app; lokalizacja / {try_files $ uri $ uri / /index.html; }}
Moin Haidar,
4
pamiętaj <base href = "/"> </base> w tagu head
Silvio Troia
Dzięki! bez tego głębokie linkowanie jest niemożliwe. Nadal nie jestem pewien, czy ładność lub identyfikatory URI są warte kłopotów z utrzymaniem tego, jeśli potrzebujesz głębokiego linkowania, szczególnie w niektórych środowiskach chmury / paas, gdzie możesz nie mieć łatwego dostępu do konfiguracji httpd.
Pierre Henry
39

Napiszmy odpowiedź, która wygląda prosto i krótko

Na końcu routera dodaj html5Mode (true) ;

app.config(function($routeProvider,$locationProvider) {

    $routeProvider.when('/home', {
        templateUrl:'/html/home.html'
    });

    $locationProvider.html5Mode(true);
})

W html head dodaj tag podstawowy

<html>
<head>
    <meta charset="utf-8">    
    <base href="/">
</head>

dzięki @plus - za wyszczególnienie powyższej odpowiedzi

Vijay
źródło
Nie udało mi się tego uruchomić. Opublikowałem nowe pytanie z moimi szczegółowymi danymi na stronie: stackoverflow.com/questions/36041074/... Proszę spojrzeć na to i jeśli możesz mi pomóc, byłbym bardzo wdzięczny.
Larry Martell,
30

próbować

$locationProvider.html5Mode(true)

Więcej informacji na $ location
Provider Korzystanie z $ location

skeep
źródło
6
przepraszam, dodałem .config (function ($ locationProvider) {$ locationProvider.html5Mode (true)}), ale mam wynik index.html #% 2Fome nie indeks.html / home
zloctb
12

Poniższe informacje pochodzą z:
https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

Bardzo łatwo jest uzyskać czyste adresy URL i usunąć hashtag z adresu URL w Angular.
Domyślnie AngularJS będzie kierować adresy URL z hashtagiem. Na przykład:

Należy zrobić 2 rzeczy.

  • Konfigurowanie $ locationProvider

  • Ustawianie naszej bazy dla linków względnych

  • Usługa lokalizacji

W Angular usługa lokalizacji $ analizuje adres URL w pasku adresu i wprowadza zmiany w aplikacji i odwrotnie.

Zdecydowanie polecam przeczytanie oficjalnej dokumentacji lokalizacji Angular $, aby poznać usługę lokalizacji i jej usługi.

https://docs.angularjs.org/api/ng/service/$location

$ locationProvider i html5Mode

  • Użyjemy modułu $ locationProvider i ustawimy html5Mode na true.
  • Zrobimy to podczas definiowania aplikacji Angular i konfigurowania tras.

    angular.module('noHash', [])
    
    .config(function($routeProvider, $locationProvider) {
    
       $routeProvider
           .when('/', {
               templateUrl : 'partials/home.html',
               controller : mainController
           })
           .when('/about', {
               templateUrl : 'partials/about.html',
               controller : mainController
           })
           .when('/contact', {
               templateUrl : 'partials/contact.html',
               controller : mainController
           });
    
       // use the HTML5 History API
       $locationProvider.html5Mode(true); });
    

Co to jest interfejs API historii HTML5? Jest to ustandaryzowany sposób manipulowania historią przeglądarki za pomocą skryptu. Dzięki temu Angular może zmienić routing i adresy URL naszych stron bez odświeżania strony. Aby uzyskać więcej informacji na ten temat, oto dobry artykuł dotyczący interfejsu API historii HTML5:

http://diveintohtml5.info/history.html

Ustawienie linków względnych

  • Aby połączyć się z aplikacją za pomocą linków względnych, musisz ustawić <base>w <head>swoim dokumencie. Może to być plik root.html Twojej aplikacji Angular. Znajdź <base>tag i ustaw go na główny adres URL, który chcesz dla swojej aplikacji.

Na przykład: <base href="https://stackoverflow.com/">

  • Istnieje wiele innych sposobów skonfigurowania tego, a tryb HTML5 ustawiony na true powinien automatycznie rozpoznawać linki względne. Jeśli katalog główny aplikacji jest inny niż adres URL (na przykład / moja-baza, użyj go jako swojej bazy).

Powrót do starszych przeglądarek

  • Usługa lokalizacji $ automatycznie powróci do metody hashbang dla przeglądarek, które nie obsługują interfejsu API historii HTML5.
  • Dzieje się to w sposób transparentny i nie trzeba niczego konfigurować, aby działało. Z dokumentów lokalizacji Angular $ można zobaczyć metodę rezerwową i sposób jej działania.

Podsumowując

  • Jest to prosty sposób na uzyskanie ładnych adresów URL i usunięcie hashtagu w aplikacji Angular. Baw się dobrze, tworząc te super czyste i super szybkie aplikacje Angular!
zero_cool
źródło
3

Jeśli chcesz to skonfigurować lokalnie w systemie OS X 10.8 obsługującym Angular z Apache, możesz znaleźć następujące informacje w pliku .htaccess:

<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /~yourusername/appname/public/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png|jpg|jpeg|gif|txt)
    RewriteRule (.*) index.html [L]
</IfModule>

Opcje + FollowSymlinks, jeśli nie jest ustawiony, może spowodować niedozwolony błąd w logach:

Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden

Wymagana jest przepisz bazę, w przeciwnym razie żądania zostaną rozstrzygnięte na twoim głównym katalogu serwera, który lokalnie domyślnie nie jest katalogiem projektu, chyba że specjalnie skonfigurowałeś vhosty, więc musisz ustawić ścieżkę, aby żądanie znalazło katalog główny projektu. Na przykład na moim komputerze mam katalog / Users / me / Sites, w którym przechowuję wszystkie moje projekty. Podobnie jak stary system OS X.

Następne dwa wiersze skutecznie mówią, jeśli ścieżka nie jest katalogiem lub plikiem, więc musisz upewnić się, że nie masz plików ani katalogów identycznych ze ścieżkami tras aplikacji.

Następny warunek mówi, że jeśli żądanie nie kończy się na określonych rozszerzeniach plików, dodaj tam, czego potrzebujesz

Ostatni [L] mówi, że ma obsługiwać plik index.html - twoją aplikację dla wszystkich innych żądań.

Jeśli nadal masz problemy, sprawdź dziennik Apache, prawdopodobnie da ci przydatne wskazówki:

/private/var/log/apache2/error_log
Pan P.
źródło
Jeśli używasz MAMP jako lokalnego serwera apache, upewnij się, że pierwszy RewriteBase jest linkiem względnym. np. RewriteBase / angularjs_site_folder /
David Douglas
3

Korzystanie z trybu HTML5 wymaga przepisywania adresów URL po stronie serwera, w zasadzie musisz przepisać wszystkie linki do punktu wejścia aplikacji (np. Index.html). Wymaganie <base>znacznika jest również ważne w tym przypadku, ponieważ umożliwia AngularJS rozróżnienie między częścią adresu URL, która jest bazą aplikacji, a ścieżką, którą powinna obsłużyć aplikacja. Aby uzyskać więcej informacji, zobacz AngularJS Developer Guide - Używanie $ location Tryb HTML5 Po stronie serwera .


Aktualizacja

Instrukcje: konfigurowanie serwera do pracy z html5Mode 1

Po włączeniu html5Mode #znak nie będzie już używany w twoich adresach URL. #Symbolem jest przydatna, ponieważ nie wymaga konfiguracji po stronie serwera. Bez #tego adres URL wygląda o wiele ładniej, ale wymaga również przepisania po stronie serwera. Oto kilka przykładów:

Apache przepisze

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

Nginx Przepisuje

server {
    server_name my-app;

    index index.html;

    root /path/to/app;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Azure IIS przepisze

<system.webServer>
  <rewrite>
    <rules> 
      <rule name="Main Rule" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

Express Rewrites

var express = require('express');
var app = express();

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

app.listen(3006); //the port you want to use

Zobacz też

georgeawg
źródło
1

W Angular 6 z routerem możesz używać:

RouterModule.forRoot(routes, { useHash: false })
Grepresland
źródło
0

Możesz również użyć poniższego kodu, aby przekierować na stronę główną (główną):

{ path: '', redirectTo: 'home', pathMatch: 'full'}

Po określeniu przekierowania jak powyżej możesz przekierować inne strony, na przykład:

{ path: 'add-new-registration', component: AddNewRegistrationComponent},
{ path: 'view-registration', component: ViewRegistrationComponent},
{ path: 'home', component: HomeComponent}
Wysypka
źródło
0

**

Zaleca się stosowanie stylu HTML 5 (PathLocationStrategy) jako strategii lokalizacji w Angular

** Ponieważ

  1. Tworzy czyste i przyjazne dla SEO adresy URL, które są łatwiejsze do zrozumienia i zapamiętania przez użytkowników.
  2. Możesz skorzystać z renderowania po stronie serwera, co przyspieszy ładowanie naszej aplikacji, najpierw renderując strony na serwerze, zanim dostarczysz go klientowi.

Użyj Hashlocationstrtegy tylko wtedy, gdy musisz obsługiwać starsze przeglądarki.

Kliknij tutaj, aby dowiedzieć się więcej

Mahendra Waykos
źródło