AngularJS маршрутизация без хеша '#'


223

Я изучаю AngularJS, и есть одна вещь, которая действительно раздражает меня.

Я использую, $routeProviderчтобы объявить правила маршрутизации для моего приложения:

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

но когда я перехожу к своему приложению в браузере, я вижу app/#/test вместо app/test.

Итак, мой вопрос: почему AngularJS добавляет этот хеш #к URL? Есть ли возможность этого избежать?


2
Вот решение, если вы используете Angular 1.6.
Мисталис

Ответы:


265

На самом деле вам нужен # (хэштег) для браузеров не HTML5.

В противном случае они просто сделают HTTP-вызов к серверу по указанному href. # - это старая короткая схема браузера, которая не запускает запрос, что позволяет многим js-фреймворкам создавать собственные клиентские перенаправления поверх этого.

Вы можете использовать $locationProvider.html5Mode(true)Angular для использования стратегии HTML5, если она доступна.

Вот список браузеров, поддерживающих стратегию HTML5: http://caniuse.com/#feat=history


4
Спасибо. Это то, что я подозревал. Но для меня это довольно недружелюбно! Допустим, я хочу, чтобы какой-то ресурс был доступен через url, app / res. Как пользователи моего сайта могут узнать, что они должны вместо этого ввести app / # / res?
pikkvile

5
Но если это так, зачем мне нужно, чтобы эти пути были видны в строке адреса? Если пользователи не будут использовать их, я могу просто сделать одностраничное приложение javascript.
pikkvile

6
Это полезно, когда вы хотите отслеживать состояние приложения. Фреймворки предлагают механизм истории. Кроме того, он позволяет получить прямой доступ к состоянию вашего приложения, например, через общий доступ к URL
плюс

6
Хэштег не требуется в современных браузерах, которые поддерживают API истории HTML5. Смотрите ответ @ skeep и предоставленные ссылки. В режиме HTML5 Angular будет использовать хэштеги, только если браузер не поддерживает его. Также обратите внимание, что вам не нужно использовать $ routeProvider, если вы не хотите ... вы можете подключить свою собственную маршрутизацию, используя ng-клики и ng-include (на самом деле вы должны сделать это, если вам нужно несколько уровней маршрутизация, так как ng-view может появляться только один раз на страницу). См. Также stackoverflow.com/questions/12793609/…
Марк Райкок

2
В случае hhml рендеринга hashbang / pushstate / server, на Twitter очень приятно читать engineering.twitter.com/2012/12/… Он объясняет, как им удалось это сделать, так что он обратно совместим со старым браузером и с поиском двигатели. Я знаю, что это не специфично для angularjs, но вы можете воспроизвести поток.
Джекдбернье

47

Если вы включили html5mode, как говорили другие, и создайте .htaccessфайл со следующим содержимым (с учетом ваших потребностей):

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]

Пользователи будут перенаправлены на ваше приложение, когда они введут правильный маршрут, и ваше приложение прочитает маршрут и выведет их на нужную «страницу» внутри него.

РЕДАКТИРОВАТЬ: Просто убедитесь, что имена файлов или каталогов не конфликтуют с вашими маршрутами


есть ли версия nginx этого? при загрузке /aboutстраницы происходит сбой, если я не захожу на нее через приложение.
Чови

Никогда не использовал их, но попробуйте это: stackoverflow.com/questions/5840497/convert-htaccess-to-nginx
bearfriend

3
@chovy - здесь идет версия nGinx: server {имя_сервера my-app; root / path / to / app; location / {try_files $ uri $ uri / /index.html; }}
Мойн Хайдар

4
помните <base href = "/"> </ base> в заголовке тега
Сильвио Троя

Спасибо! без этого глубокое связывание невозможно. Я до сих пор не уверен, что красивость или URI стоит того, чтобы их поддерживать, если вам нужна глубокая связь, особенно в некоторых облачных / paas средах, где у вас может не быть легкого доступа к httpd config.
Пьер Генри

39

Давайте напишем ответ, который выглядит простым и коротким

В конце Router добавьте html5Mode (true) ;

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

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

    $locationProvider.html5Mode(true);
})

В html head добавьте базовый тег

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

спасибо @plus - за детализацию приведенного выше ответа


Я не смог заставить это работать. Я разместил новый вопрос со своими конкретными данными по адресу: stackoverflow.com/questions/36041074/… Пожалуйста, посмотрите на это, и если вы можете помочь, я был бы очень признателен.
Ларри Мартелл


12

Следующая информация от:
https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

Очень легко получить чистые URL и удалить хэштег из URL в Angular.
По умолчанию AngularJS будет направлять URL-адреса с помощью хэштега. Например:

Есть 2 вещи, которые нужно сделать.

  • Настройка $ locationProvider

  • Настройка нашей базы для относительных ссылок

  • $ Location Service

В Angular служба $ location анализирует URL-адрес в адресной строке и вносит изменения в ваше приложение, и наоборот.

Я настоятельно рекомендую ознакомиться с официальными документами Angular $ location, чтобы получить представление о службе определения местоположения и ее услугах.

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

$ locationProvider и html5Mode

  • Мы будем использовать модуль $ locationProvider и установить для html5Mode значение true.
  • Мы сделаем это при определении вашего приложения Angular и настройке ваших маршрутов.

    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); });

Что такое API истории HTML5? Это стандартизированный способ манипулирования историей браузера с использованием скрипта. Это позволяет Angular изменять маршрутизацию и URL-адреса наших страниц без обновления страницы. Для получения дополнительной информации об этом, вот хорошая статья API Истории HTML5:

http://diveintohtml5.info/history.html

Настройка для относительных ссылок

  • Чтобы связать ваше приложение с помощью относительных ссылок, вам нужно будет указать <base>в <head>документе. Это может быть в корневом файле index.html вашего приложения Angular. Найдите <base>тег и задайте для него корневой URL-адрес, который вы хотите использовать в своем приложении.

Например: <base href="https://stackoverflow.com/">

  • Есть много других способов настроить это, и режим HTML5, установленный в true, должен автоматически разрешать относительные ссылки. Если ваш корень приложения отличается от URL-адреса (например, / my-base, используйте его в качестве базы).

Резервный вариант для старых браузеров

  • Служба $ location автоматически переключится на метод hashbang для браузеров, которые не поддерживают API истории HTML5.
  • Это происходит прозрачно для вас, и вам не нужно ничего настраивать для его работы. Из документов Angular $ location вы можете увидеть запасной метод и узнать, как он работает.

В заключение

  • Это простой способ получить красивые URL-адреса и удалить хэштег в вашем приложении Angular. Получайте удовольствие, делая эти супер чистые и супер быстрые приложения Angular!

3

Если вы хотите настроить это локально на OS X 10.8, обслуживающей Angular с Apache, тогда вы можете найти следующее в вашем файле .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>

Опции + FollowSymlinks, если не установлены, могут привести к запрещенной ошибке в журналах, например:

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

Требуется перезапись базы, в противном случае запросы будут разрешены к корневому каталогу вашего сервера, который локально по умолчанию не является каталогом вашего проекта, если вы специально не настроили свои vhosts, поэтому вам нужно задать путь, чтобы запрос нашел корневой каталог вашего проекта. Например, на моей машине у меня есть каталог / Users / me / Sites, где я храню все свои проекты. Как старая OS X настроена.

В следующих двух строках фактически указывается, является ли путь не каталогом или файлом, поэтому необходимо убедиться, что у вас нет файлов или каталогов, совпадающих с путями маршрутизации приложения.

Следующее условие говорит, что если запрос не заканчивается указанными расширениями, добавьте туда, что вам нужно

И последний [L] говорит, что нужно обслуживать файл index.html - ваше приложение для всех остальных запросов.

Если у вас все еще есть проблемы, проверьте журнал apache, он, вероятно, даст вам полезные советы:

/private/var/log/apache2/error_log

Если вы используете MAMP в качестве локального сервера Apache, убедитесь, что первая RewriteBase является относительной ссылкой. например, RewriteBase / angularjs_site_folder /
Дэвид Дуглас

3

Использование режима HTML5 требует перезаписи URL на стороне сервера, в основном вы должны переписать все ваши ссылки на точку входа вашего приложения (например, index.html). Требование <base>тега также важно для этого случая, поскольку оно позволяет AngularJS различать часть URL-адреса, которая является базой приложения, и путь, который должен обрабатываться приложением. Для получения дополнительной информации см. Руководство разработчика AngularJS - Использование $ location в режиме HTML5 на стороне сервера .


Обновить

Как: настроить сервер для работы с html5Mode 1

Когда у вас включен html5Mode, #персонаж больше не будет использоваться в ваших URL. #Символ является полезным , поскольку он не требует настроек на стороне сервера. Без #этого URL выглядит намного лучше, но он также требует переписывания на стороне сервера. Вот некоторые примеры:

Apache переписывает

<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 переписывает

server {
    server_name my-app;

    index index.html;

    root /path/to/app;

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

Azure IIS переписывает

<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>

Экспресс переписывает

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

Смотрите также


1

В Angular 6 с вашим роутером вы можете использовать:

RouterModule.forRoot(routes, { useHash: false })

0

Вы также можете использовать приведенный ниже код для перенаправления на главную страницу (домой):

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

После указания вашего перенаправления, как указано выше, вы можете перенаправить другие страницы, например:

{ path: 'add-new-registration', component: AddNewRegistrationComponent},
{ path: 'view-registration', component: ViewRegistrationComponent},
{ path: 'home', component: HomeComponent}

0

**

Рекомендуется использовать стиль HTML 5 (PathLocationStrategy) в качестве стратегии определения местоположения в Angular.

** Потому что

  1. Он производит чистые и дружественные к SEO URL-адреса, которые пользователям легче понять и запомнить.
  2. Вы можете воспользоваться рендерингом на стороне сервера, который ускорит загрузку нашего приложения, предварительно отрисовав страницы на сервере перед его доставкой клиенту.

Используйте Hashlocationstrtegy, только если вы должны поддерживать старые браузеры.

Нажмите здесь, чтобы узнать больше

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.