$ location / html5와 hashbang 모드 간 전환 / 링크 재 작성


179

Angular가 템플릿 내 앵커 태그의 href 속성에 나타나는 URL을 다시 작성하여 html5 모드 또는 hashbang 모드에서 작동한다는 인상을 받았습니다. 위치 서비스에 대한 문서는 HTML 링크 재 작성은 hashbang 상황을 담당 말할 것 같다. 따라서 HTML5 모드가 아닌 경우 해시가 삽입되고 HTML5 모드에서는 해시가 삽입되지 않을 것으로 예상합니다.

그러나 다시 쓰기가 수행되지 않는 것 같습니다. 다음 예제에서는 모드를 변경할 수 없습니다. 응용 프로그램의 모든 링크는 직접 다시 작성해야합니다 (또는 런타임에 변수에서 파생되어야합니다. 모드에 따라 모든 URL을 수동으로 다시 작성해야합니까?

Angular 1.0.6, 1.1.4 또는 1.1.3에서 클라이언트 측 URL 재 작성이 진행되지 않습니다. 모든 href 값 앞에 hashbang 모드의 경우 # /와 html5 모드의 앞에 /를 붙여야합니다.

다시 쓰려면 일부 구성이 필요합니까? 문서를 잘못 읽고 있습니까? 바보 같은 일을합니까?

다음은 작은 예입니다.

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

부록 : 내 질문을 다시 읽을 때, 나는 언제 그리고 언제 다시 쓰기를하고 싶었는지를 명확하게하지 않고 "다시 쓰기"라는 용어를 사용했음을 알 수 있습니다. 문제는 경로를 렌더링 할 때 URL을 다시 작성 하기 위해 Angular 를 얻는 방법 과 두 모드에서 JS 코드의 경로를 균일하게 해석하는 방법에 관한 것입니다. 웹 서버가 HTML5 호환 요청을 다시 쓰도록하는 방법에 관한 것이 아닙니다 .


1
다음은 Angular 1.6에 대한 솔루션 입니다 .
Mistalis

답변:


361

AngularJS 라우팅에 대한 문서는 명확하지 않습니다. Hashbang 및 HTML5 모드에 대해 설명합니다. 실제로 AngularJS 라우팅은 세 가지 모드로 작동합니다.

  • 해시 방 모드
  • HTML5 모드
  • HTML5 모드의 Hashbang

각 모드마다 각각의 LocationUrl 클래스 (LocationHashbangUrl, LocationUrl 및 LocationHashbangInHTML5Url)가 있습니다.

URL 재 작성을 시뮬레이션하려면 실제로 html5mode를 true로 설정하고 다음과 같이 $ sniffer 클래스를 장식해야합니다.

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

이제 이것을 자세히 설명하겠습니다.

해시 방 모드

구성 :

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

HTML 파일에서 해시와 함께 URL을 사용해야하는 경우와 같습니다.

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

브라우저에서 다음 링크를 사용해야합니다. http://www.example.com/base/index.html#!/base/path

순수한 Hashbang 모드에서 볼 수 있듯이 HTML 파일의 모든 링크는 "index.html #!"와 같이 기본으로 시작해야합니다.

HTML5 모드

구성 :

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

HTML 파일에서 기본을 설정해야합니다

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

이 모드에서는 HTML 파일에서 #없이 링크를 사용할 수 있습니다

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

브라우저에서 링크 :

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

HTML5 모드의 Hashbang

이 모드는 실제로 HTML5 모드를 사용하지만 호환되지 않는 브라우저에서 활성화됩니다. $ sniffer 서비스를 장식하고 기록을 false로 설정하여 호환되는 브라우저에서이 모드를 시뮬레이션 할 수 있습니다.

구성 :

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

HTML 파일에서 기본을 설정하십시오.

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

이 경우 HTML 파일에서 해시없이 링크를 작성할 수도 있습니다.

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

브라우저에서 링크 :

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

@jupiter에 대한 자세한 설명에 감사드립니다. 뱅을 건너 뛰고 해시를 유지하고 Angular가 모드에 따라 두 개의 URL 세트를 요구하지 않도록 속일 수 있는지 살펴 보겠습니다!
laurelnaiad

1
귀하의 문제를 제대로 이해하지 못했다고 생각합니다. 왜 해시없이 URL 만 사용하지 않습니까? 히스토리 API를 지원하는 브라우저 및 히스토리 API를 지원하지 않는 브라우저에서 작동합니다. AngularJS는 링크 클릭을 가로 채기 때문에 히스토리 API를 지원하지 않는 브라우저에서 버전을 클릭하면 위치 표시 줄에 # 버전을 배치합니다.
목성

두 모드를 모두 지원 해야하는 프레임 워크에서 작업하고 있습니다. 앱 작성자는 템플릿에 해시가 있는지 여부 및 / 또는 상대 경로 해석의 변경 사항에 대해 걱정하지 않고 둘 중 하나를 선택할 수 있어야합니다. 실용적인 해결책이 "모드를 html5로 설정 한 다음 브라우저 기능에 대해 각도를두고 있음에도 불구하고"모드를 변경하기 만하면됩니다.
laurelnaiad

1
나는 $provide정의되지 않고 있습니까?
Petrus Theron

1
@pate-데코레이터를 설정할 때 구성 기능에 $ provide를 주입해야합니다.
laurelnaiad

8

미래의 독자라면 Angular 1.6을 사용하는 경우 다음 을 변경해야합니다 hashPrefix.

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

HTML에서 기본을 설정하는 것을 잊지 마십시오 <head>.

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

changelog에 대한 추가 정보 here.


3
감사합니다 @Mistalis. 당신의 대답은 잘 작동합니다. 라우팅 후 페이지를 새로 고치면 페이지를 찾을 수 없음 오류가 발생합니다. 도와주세요 ..
Ashish Mehta

@AshishMehta 안녕하세요 Ashish. 이 답변 을 읽으 십시오. 문제를 해결할 수 있습니다. 안녕! :)
Mistalis

0

SEO에 대한 #없이 Angular WebAPI ASP Routing-이것이 작동하는 방식입니다.

  1. Index.html에 추가-base href = "/">
  2. $ locationProvider.html5Mode (true);를 추가하십시오. app.config로

  3. 이미지를 업로드 할 때 특정 컨트롤러 (홈 컨트롤러에 있음)를 무시해야하므로 해당 규칙을 RouteConfig에 추가했습니다

         routes.MapRoute(
            name: "Default2",
            url: "Home/{*.}",
            defaults: new { controller = "Home", action = "SaveImage" }
        );
  4. Global.asax에서 다음을 추가하십시오-api 및 이미지 업로드 경로를 무시하면 정상적으로 작동하고 그렇지 않으면 다른 모든 경로를 다시 지정합니다.

     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. window.location ...이 아닌 $ location.url ( '/ XXX')을 사용하여 리디렉션하십시오.

  6. 절대 경로로 CSS 파일 참조

그리고 아닙니다

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

마지막 참고 사항-이 방법으로 나에게 모든 권한을 부여했으며 웹 구성에 아무것도 할 필요가 없었습니다.

이것이 도움이되기를 바랍니다.


0

HTML5 모드와 고정 토큰으로 응용 프로그램에 액세스 한 다음 hashbang 메서드로 전환하여 사용자가 자신의 페이지를 새로 고칠 수 있도록 토큰을 유지하려고했습니다.

내 앱에 액세스하기위한 URL :

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

그런 다음 사용자가 페이지를로드하면

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

그런 다음 사용자가 탐색 할 때 :

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

이를 통해 토큰을 URL에 유지하고 사용자가 탐색 할 때 상태를 유지합니다. URL의 가시성을 약간 잃어 버렸지 만 완벽한 방법은 없습니다.

HTML5 모드를 활성화하지 말고이 컨트롤러를 추가하십시오 :

.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' })
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.