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

Відповіді:


265

Насправді вам потрібен # (хештег) для браузерів, які не входять у HTML5.

Інакше вони просто зроблять HTTP-дзвінок на сервер у згаданому href. # - це стара мікросхема браузера, яка не запускає запит, що дозволяє багатьом js-фреймворкам створювати власні клієнтські перенаправлення поверх цього.

Ви можете $locationProvider.html5Mode(true)вказати кутовий, щоб використовувати стратегію HTML5, якщо вона є.

Ось список браузера, який підтримує стратегію HTML5: http://caniuse.com/#feat=history


4
Добре, дякую. Це те, в чому я підозрював. Але як на мене, це досить непривітно для користувачів! Скажімо, я хочу, щоб якийсь ресурс був доступний через URL, додаток / res. Як користувачі мого сайту можуть дізнатись, що вони повинні набрати додаток / # / res?
pikkvile

5
Якщо так, то для чого мені потрібні ці шляхи, щоб вони були видні в рядку розташування? Якщо користувачі не використовуватимуть їх, я можу просто зробити односторінкове додаток javascript.
pikkvile

6
Це корисно, коли ви хочете слідкувати за станом програми. Рамки пропонують механізм історії. Крім того, він дозволяє отримати прямий доступ до стану вашої програми, наприклад, через спільний доступ до URL
плюс

6
У сучасних браузерах, які підтримують API історії HTML5, хештег не потрібен. Дивіться відповідь @ skeep та надані посилання. У режимі HTML5 Angular буде використовувати хештеги, лише якщо браузер не підтримує його. Зауважте також, що вам не доведеться використовувати $ routeProvider, якщо ви не хочете ... ви можете прокласти свою власну маршрутизацію за допомогою ng-клацань і ng-include (насправді вам потрібно зробити це, якщо вам потрібно кілька рівнів маршрутизація, оскільки ng-view може з’являтися лише один раз на сторінці). Дивіться також stackoverflow.com/questions/12793609 / ...
Відзначити Rajcok

2
У випадку html-рендеринга на базі хешбангу / pushstate / сервера, Twitter досить приємно читати Engineering.twitter.com/2012/12/… Він пояснює, як їм це вдалося зробити так, щоб це було сумісним із старим браузером та з пошуком двигуни. Я знаю, що це не конкретно для angularjs, але ви можете відтворити потік.
jackdbernier

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сторінку не вдається, якщо я не заходжу на неї через додаток.
chovy

Ніколи не використовував їх, але спробуйте це: stackoverflow.com/questions/5840497/convert-htaccess-to-nginx
bearfriend

3
@chovy - сюди йде версія nGinx: сервер {server_name my-app; корінь / шлях / до / додаток; location / {try_files $ uri $ uri / /index.html; }}
Мойн Гайдар

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

Дякую! без цього глибоке пов'язування неможливо. Я до цих пір не впевнений, що принадність або URI варті труднощів у підтримці цього, якщо вам потрібно глибоке посилання, особливо в деяких хмарних / пайових середовищах, у яких, можливо, не буде легкого доступу до конфігурації httpd.
П’єр Генрі

39

Дозволяє писати відповідь, яка виглядає просто і коротко

В маршрутизатор в кінці додайте 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

  • Налаштування нашої бази для відносних посилань

  • $ Місцезнаходження

У 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 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 автоматично повернеться до методу хешбангу для веб-переглядачів, які не підтримують API історії HTML5.
  • Це відбувається з вами прозоро, і вам не доведеться нічого конфігурувати, щоб він працював. З документів Angular $ location ви можете побачити метод резервного копіювання та як він працює.

У висновку

  • Це простий спосіб отримати гарні URL-адреси та видалити хештег у вашій програмі 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

У кутовому 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.