Angular2+URL中的 # 引发的思考

1.先分析 # 的作用

1.1. # 的涵义

 #代表网页中的位置。其右面的字符就是该位置的标识符。比如,http://www.example.com/index.html#print就代表网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。

#是指导浏览器动作的,对服务器完全无效。所以HTTP请求不会包含#及右侧内容

1.2.HTTP请求不包括#

#是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP请求中不包括#。
比如,访问下面的网址,http://www.example.com/index.html#print,浏览器实际发出的请求是这样的:

GET /index.html HTTP/1.1
Host: www.example.com

1.3.#后的字符

在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。
比如,下面URL的原意是指定一个颜色值:http://www.example.com/?color=#fff,但是,浏览器实际发出的请求是:

GET /?color= HTTP/1.1
Host: www.example.com

1.4.改变#不触发网页重载

单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页。
比如,从http://www.example.com/index.html#location1改成http://www.example.com/index.html#location2,浏览器不会重新向服务器请求index.html。

1.5.改变#会改变浏览器的访问历史

每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。这对于ajax应用程序特别有用,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。值得注意的是,上述规则对IE 6和IE 7不成立,它们不会因为#的改变而增加历史记录。

1.6.window.location.hash读取#值

window.location.hash这个属性可读可写。读取时,可以用来判断网页状态是否改变;写入时,则会在不重载网页的前提下,创造一条访问历史记录。

1.7.onhashchange事件

这是一个HTML 5新增的事件,当#值发生变化时,就会触发这个事件。IE8+、Firefox 3.6+、Chrome 5+、Safari 4.0+支持该事件。
它的使用方法有三种:

  • window.onhashchange = func;
  • <body onhashchange="func();">
  • window.addEventListener("hashchange", func, false);

2.那使用还是不使用 # 呢?

2.1.为什么要去除

  • Angular官方指出:如果没有足够使用hash风格(#)的理由,还是尽量使用HTML5模式的路由风格;

  • 如果配置了hash风格,在微信支付或是Angular的深路径依然会出404的问题;

  • 当你需要使用GA等工具时,由于无法获取#号后的URL,导致每次路由切换都给其发送一个路径;

  • '#'有点丑。

2.2.怎样去除?

后端(Tomcat)

Tomcat/conf/web.xml文件上添加

<error-page>
    <error-code>404</error-code>
    <location>/</location>
</error-page>

3.带‘#’和不带‘#’原理上有什么区别呢?

3.1.这个得先说下什么是前端路由

以前路由都是后台做的,通过用户请求的url导航到具体的html页面,现在我们在前端可以利用 Angular、vue、react等通过配置文件,达到前端控制路由跳转的功能。

前端路由的实现方法:

  1. 通过hash实现 当url的hash发生改变时,触发hashchange注册的回调(低版本没有hashchange事件,通过轮回检测url实现),回调中去进行不同的操作,进行不同的内容展示。
    使用hash来实现的话,URI规则中要带上#,路由中#后边的内容就是hash,我们常说的锚点严格来说应该是页面中的a[name]等元素。

  2. HTML5的history api操作浏览器的session history实现
    基于history实现的路由中不带#,就是原始的路由

3.2 Angular中的路由策略

Angular2 提供的路由策略也是基于上面两个原理实现的,可以在@NgModule中通过providers配置或RouterModule.forRoot()配置:

不使用#:

默认是不使用#(Hash)风格的,即html5路由风格(无#),在无#情况下,后端需要定义能匹配所有页面请求导向index.html页面的路由。

使用 #:

app.module.ts

import { ROUTER_CONFIG } from './app.routes.ts';
@NgModule({
   imports: [
    RouterModule.forRoot(ROUTER_CONFIG) 
   //  RouterModule.forRoot(ROUTER_CONFIG, { useHash: true } )   这样写是带#的
  ],  
})

  或


  import { HashLocationStrategy, LocationStrategy } from '@angular/common';
@NgModule({
  imports:[RouterModule.forRoot(routes)],
  providers:[
     {provide: LocationStrategy, useClass: HashLocationStrategy} 
  ]
})

3.3.前端路由的优缺点

优点:

  1. 从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。
  2. 在某些场合中,用ajax请求,可以让页面无刷新,页面变了但Url没有变化,用户不能获取到想要的url地址,用前端路由做单页面网页就很好的解决了这个问题。

缺点:

  1. 使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存。
原文地址:https://www.cnblogs.com/Failbs/p/9662296.html