$location / switching between html5 and hashbang mode / link rewriting

前端 未结 4 1613
情深已故
情深已故 2020-11-22 01:49

I was under the impression that Angular would rewrite URLs that appear in href attributes of anchor tags within tempaltes, such that they would work whether in html5 mode or

相关标签:
4条回答
  • 2020-11-22 02:32

    Fur future readers, if you are using Angular 1.6, you also need to change the hashPrefix:

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

    Don't forget to set the base in your HTML <head>:

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

    More info about the changelog here.

    0 讨论(0)
  • 2020-11-22 02:35

    The documentation is not very clear about AngularJS routing. It talks about Hashbang and HTML5 mode. In fact, AngularJS routing operates in three modes:

    • Hashbang Mode
    • HTML5 Mode
    • Hashbang in HTML5 Mode

    For each mode there is a a respective LocationUrl class (LocationHashbangUrl, LocationUrl and LocationHashbangInHTML5Url).

    In order to simulate URL rewriting you must actually set html5mode to true and decorate the $sniffer class as follows:

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

    I will now explain this in more detail:

    Hashbang Mode

    Configuration:

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

    This is the case when you need to use URLs with hashes in your HTML files such as in

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

    In the Browser you must use the following Link: http://www.example.com/base/index.html#!/base/path

    As you can see in pure Hashbang mode all links in the HTML files must begin with the base such as "index.html#!".

    HTML5 Mode

    Configuration:

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

    You should set the base in HTML-file

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

    In this mode you can use links without the # in HTML files

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

    Link in Browser:

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

    Hashbang in HTML5 Mode

    This mode is activated when we actually use HTML5 mode but in an incompatible browser. We can simulate this mode in a compatible browser by decorating the $sniffer service and setting history to false.

    Configuration:

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

    Set the base in HTML-file:

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

    In this case the links can also be written without the hash in the HTML file

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

    Link in Browser:

    http://www.example.com/index.html#!/base/path
    
    0 讨论(0)
  • 2020-11-22 02:37

    I wanted to be able to access my application with the HTML5 mode and a fixed token and then switch to the hashbang method (to keep the token so the user can refresh his page).

    URL for accessing my app:

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

    Then when the user loads the page:

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

    Then when the user navigates:

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

    With this I keep the token in the URL and keep the state when the user is browsing. I lost a bit of visibility of the URL, but there is no perfect way of doing it.

    So don't enable the HTML5 mode and then add this controller:

    .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' })
    
    0 讨论(0)
  • 2020-11-22 02:54

    This took me a while to figure out so this is how I got it working - Angular WebAPI ASP Routing without the # for SEO

    1. add to Index.html - base href="/">
    2. Add $locationProvider.html5Mode(true); to app.config

    3. I needed a certain controller (which was in the home controller) to be ignored for uploading images so I added that rule to RouteConfig

           routes.MapRoute(
              name: "Default2",
              url: "Home/{*.}",
              defaults: new { controller = "Home", action = "SaveImage" }
          );
      
    4. In Global.asax add the following - making sure to ignore api and image upload paths let them function as normal otherwise reroute everything else.

       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. Make sure to use $location.url('/XXX') and not window.location ... to redirect

    6. Reference the CSS files with absolute path

    and not

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

    Final note - doing it this way gave me full control and I did not need to do anything to the web config.

    Hope this helps as this took me a while to figure out.

    0 讨论(0)
提交回复
热议问题