การกำหนดเส้นทาง AngularJS โดยไม่มีแฮช '#'


223

ฉันกำลังเรียนรู้ AngularJS และมีสิ่งหนึ่งที่ทำให้ฉันรำคาญจริงๆ

ฉันใช้$routeProviderเพื่อประกาศกฎการกำหนดเส้นทางสำหรับแอปพลิเคชันของฉัน:

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

แต่เมื่อฉันนำทางไปยังแอปของฉันในเบราว์เซอร์ที่ฉันเห็นแทนapp/#/testapp/test

ดังนั้นคำถามของฉันคือทำไม AngularJS เพิ่มแฮชนี้#เพื่อ URL? มีความเป็นไปได้ที่จะหลีกเลี่ยงหรือไม่?


2
นี่คือวิธีแก้ปัญหาหากคุณใช้ Angular 1.6
Mistalis

คำตอบ:


265

ในความเป็นจริงคุณต้องมี # (hashtag) สำหรับเบราว์เซอร์ที่ไม่ใช่ HTML5

มิฉะนั้นพวกเขาจะทำการโทร HTTP ไปยังเซิร์ฟเวอร์ที่ href ที่กล่าวถึง # เป็น shortcircuit เบราว์เซอร์เก่าซึ่งไม่ได้ดำเนินการตามคำขอซึ่งช่วยให้เฟรมเวิร์ก js จำนวนมากสามารถสร้างการกำหนดเส้นทางใหม่ให้กับไคลเอ็นต์ของตนเองได้

คุณสามารถใช้$locationProvider.html5Mode(true)เพื่อบอกมุมให้ใช้กลยุทธ์ HTML5 ถ้ามี

นี่คือรายการเบราว์เซอร์ที่รองรับกลยุทธ์ HTML5: http://caniuse.com/#feat=history


4
โอเคขอบคุณ. นี่คือสิ่งที่ฉันสงสัย แต่สำหรับฉันแล้วมันค่อนข้างเป็นมิตรกับผู้ใช้! สมมติว่าฉันต้องการให้ทรัพยากรบางอย่างผ่าน url, app / res ผู้ใช้เว็บไซต์ของฉันจะทราบได้อย่างไรว่าพวกเขาควรพิมพ์ app / # / res แทน
pikkvile

5
แต่ถ้าเป็นเช่นนั้นเหตุใดฉันจึงต้องการให้เส้นทางเหล่านี้ปรากฏในแถบตำแหน่งที่ตั้ง หากผู้ใช้จะไม่ใช้พวกเขาฉันสามารถสร้างแอปพลิเคชันจาวาสคริปต์หน้าเดียว
pikkvile

6
มันมีประโยชน์เมื่อคุณต้องการติดตามสถานะแอปพลิเคชัน กรอบเสนอกลไกประวัติศาสตร์ นอกจากนี้ยังอนุญาตให้เข้าถึงสถานะแอปพลิเคชันของคุณโดยตรงผ่านการแชร์ URL เช่น
บวก -

6
ไม่จำเป็นต้องใช้แฮชแท็กในเบราว์เซอร์สมัยใหม่ที่รองรับ API ประวัติ HTML5 ดูคำตอบของ @ skeep และลิงก์ที่ให้ไว้ ในโหมด HTML5 Angular จะใช้แฮชแท็กหากเบราว์เซอร์ไม่รองรับเท่านั้น โปรดทราบว่าคุณไม่จำเป็นต้องใช้ $ routeProvider หากคุณไม่ต้องการ ... คุณสามารถวางสายการกำหนดเส้นทางของคุณเองโดยใช้ ng-clicks และ ng-include (อันที่จริงคุณต้องทำเช่นนี้หากคุณต้องการหลายระดับ การกำหนดเส้นทางเนื่องจาก ng-view สามารถปรากฏได้เพียงหนึ่งครั้งต่อหน้า) ดูstackoverflow.com/questions/12793609/…
Mark Rajcok

2
สำหรับกรณี html hingbang / pushstate / ฝั่งเซิร์ฟเวอร์การแสดงผล Twitter นั้นค่อนข้างดีที่จะอ่านengineering.twitter.com/2012/12/…มันอธิบายวิธีที่พวกเขาจัดการเพื่อให้มันเข้ากันได้กับเบราว์เซอร์เก่าและการค้นหา เครื่องมือ ฉันรู้ว่ามันไม่ได้เป็นเชิงมุม แต่คุณสามารถทำซ้ำการไหล
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; }}
Moin Haidar

4
จำ <base href = "/"> </base> ในแท็กหัว
Silvio Troia

ขอบคุณ! หากปราศจากสิ่งนี้การเชื่อมโยงที่ล้ำลึกเป็นไปไม่ได้ ฉันยังไม่แน่ใจว่าความน่ารักหรือ URIs นั้นคุ้มค่ากับปัญหาของการดูแลรักษานี้หรือไม่หากคุณต้องการการเชื่อมโยงที่ลึกโดยเฉพาะอย่างยิ่งในสภาพแวดล้อมคลาวด์ / พานาส
ปิแอร์เฮนรี

39

ให้เขียนคำตอบที่ดูเรียบง่ายและสั้น

ใน Router at end ให้เพิ่ม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/…โปรดดูที่สิ่งนี้และหากคุณสามารถช่วยได้ฉันจะขอบคุณเป็นอย่างมาก
Larry Martell


12

ข้อมูลต่อไปนี้มาจาก:
https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

มันง่ายมากที่จะได้ URL ที่สะอาดและลบแฮชแท็กจาก URL ใน Angular
โดยค่าเริ่มต้น AngularJS จะกำหนดเส้นทาง URL ด้วยแฮชแท็กตัวอย่างเช่น

มี 2 ​​สิ่งที่ต้องทำ

  • การกำหนดค่า $ locationProvider

  • การตั้งค่าฐานของเราสำหรับลิงก์ที่เกี่ยวข้อง

  • บริการระบุตำแหน่ง

ใน Angular บริการ $ location จะแยกวิเคราะห์ URL ในแถบที่อยู่และทำการเปลี่ยนแปลงแอปพลิเคชันของคุณและในทางกลับกัน

ฉันขอแนะนำให้อ่านเอกสารตำแหน่งของ Angular $ อย่างเป็นทางการเพื่อให้เข้าใจถึงบริการตำแหน่งและสิ่งที่ให้

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

$ locationProvider และ html5Mode

  • เราจะใช้โมดูล $ locationProvider และตั้งค่า html5Mode เป็นจริง
  • เราจะทำสิ่งนี้เมื่อกำหนดแอปพลิเคชันเชิงมุมของคุณและกำหนดเส้นทางของคุณ

    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>เอกสารของคุณ สิ่งนี้อาจอยู่ในไฟล์ root index.html ของแอปเชิงมุมของคุณ ค้นหา<base>แท็กและตั้งเป็น URL รากที่คุณต้องการสำหรับแอปของคุณ

ตัวอย่างเช่น: <base href="https://stackoverflow.com/">

  • มีวิธีอื่นมากมายในการกำหนดค่านี้และโหมด HTML5 ที่ตั้งค่าเป็นจริงควรแก้ไขลิงก์ที่เกี่ยวข้องโดยอัตโนมัติ หากรูทของแอปพลิเคชันของคุณแตกต่างจาก URL (เช่น / my-base ให้ใช้มันเป็นฐานของคุณ

ทางเลือกสำหรับเบราว์เซอร์รุ่นเก่า

  • บริการตำแหน่ง $ จะย้อนกลับไปยังวิธี hashbang สำหรับเบราว์เซอร์ที่ไม่รองรับ API ประวัติ HTML5 โดยอัตโนมัติ
  • สิ่งนี้เกิดขึ้นกับคุณอย่างโปร่งใสและคุณจะไม่ต้องกำหนดค่าอะไรให้มันใช้งานได้ จากเอกสารตำแหน่งของ Angular $ คุณสามารถดูวิธีสำรองได้และวิธีการทำงาน

สรุปแล้ว

  • นี่เป็นวิธีง่ายๆในการรับ URL ที่สวยงามและลบแฮชแท็กในแอปพลิเคชันเชิงมุมของคุณ ขอให้สนุกกับแอพเชิงมุมที่สะอาดและเร็วสุด ๆ !

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

จำเป็นต้องมีฐานการเขียนซ้ำมิฉะนั้นคำขอจะได้รับการแก้ไขไปยังรูทเซิร์ฟเวอร์ของคุณซึ่งโดยค่าเริ่มต้นไม่ใช่ไดเรกทอรีโครงการของคุณเว้นแต่ว่าคุณได้กำหนดค่าโฮสต์ของคุณโดยเฉพาะดังนั้นคุณต้องกำหนดเส้นทางเพื่อให้คำขอค้นหาไดเรกทอรีรากโครงการของคุณ ตัวอย่างเช่นในเครื่องของฉันฉันมีไดเรกทอรี / Users / me / Sites ที่ฉันเก็บโครงการทั้งหมดไว้ เช่นเดียวกับการตั้งค่า OS X แบบเก่า

สองบรรทัดถัดไปบอกได้อย่างมีประสิทธิภาพหากเส้นทางไม่ใช่ไดเรกทอรีหรือไฟล์ดังนั้นคุณต้องแน่ใจว่าคุณไม่มีไฟล์หรือไดเรกทอรีเหมือนกับเส้นทางเส้นทางของแอพ

เงื่อนไขต่อไปบอกว่าถ้าคำขอไม่ได้ลงท้ายด้วยนามสกุลไฟล์ที่ระบุดังนั้นเพิ่มสิ่งที่คุณต้องการ

และ [L] สุดท้ายจะบอกว่าให้บริการไฟล์ index.html - แอปของคุณสำหรับคำขออื่น ๆ ทั้งหมด

หากคุณยังมีปัญหาอยู่ให้ตรวจสอบบันทึกการทำงานของ apache อาจเป็นประโยชน์สำหรับคุณ:

/private/var/log/apache2/error_log

หากคุณใช้ MAMP เป็นเซิร์ฟเวอร์ Apache ในพื้นที่ของคุณตรวจสอบให้แน่ใจว่า RewriteBase แรกนั้นเป็นลิงก์ที่เกี่ยวข้อง เช่น RewriteBase / angularjs_site_folder /
David Douglas

3

การใช้โหมด HTML5 ต้องมีการเขียน URL ใหม่ในฝั่งเซิร์ฟเวอร์โดยทั่วไปคุณต้องเขียนลิงค์ทั้งหมดของคุณไปยังจุดเริ่มต้นของแอปพลิเคชันของคุณ (เช่น index.html) การขอ<base>แท็กก็มีความสำคัญสำหรับกรณีนี้เนื่องจาก AngularJS สามารถแยกความแตกต่างระหว่างส่วนของ url ที่เป็นฐานแอปพลิเคชันและเส้นทางที่ควรจัดการโดยแอปพลิเคชัน สำหรับข้อมูลเพิ่มเติมโปรดดูที่AngularJS ผู้พัฒนาคู่มือ - การใช้ HTML5 ที่ตั้งด้านข้างโหมดเซิร์ฟเวอร์


ปรับปรุง

วิธีการ: กำหนดค่าเซิร์ฟเวอร์ของคุณให้ทำงานกับ html5Mode 1

เมื่อคุณเปิดใช้งาน html5Mode แล้ว#อักขระนั้นจะไม่ถูกใช้ใน URL ของคุณอีกต่อไป #สัญลักษณ์จะเป็นประโยชน์เพราะมันไม่จำเป็นต้องมีการกำหนดค่าฝั่งเซิร์ฟเวอร์ โดยไม่ต้อง#URL ดูเหมือน nicer มาก แต่ก็ต้องมีการเขียนฝั่งเซิร์ฟเวอร์ นี่คือตัวอย่างบางส่วน:

Apache Rewrites

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

<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. มันสร้าง URL ที่สะอาดและเป็นมิตรกับ SEO ซึ่งง่ายสำหรับผู้ใช้ในการทำความเข้าใจและจดจำ
  2. คุณสามารถใช้ประโยชน์จากการเรนเดอร์ฝั่งเซิร์ฟเวอร์ซึ่งจะทำให้แอปพลิเคชันของเราโหลดเร็วขึ้นโดยการเรนเดอร์เพจในเซิร์ฟเวอร์ก่อนที่จะส่งมอบไคลเอ็นต์

ใช้ Hashlocationstrtegy เฉพาะเมื่อคุณต้องสนับสนุนเบราว์เซอร์รุ่นเก่า

คลิกที่นี่เพื่อทราบข้อมูลเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.