两种实现前端路由的方式

3,096 阅读5分钟

(扩展思路:路由?前端路由与后端路由?前端路由两种实现方式?)

1、什么是路由呢?
路由就是根据不同的url地址展示不同的页面或者内容。

2、什么是前端路由,什么是后端路由,以及它们有什么异同?
前端路由是指:不同的url地址对应到不同的内容或页面这个任务是由前端来完成的,就是前端路由,前端路由是不会刷新页面的,随着SPA单页应用的普及,以及前后端分离,现在的项目基本上都是前端路由。 优点:前后端的彻底分离,不刷新页面,用户体验较好,页面持久性较好,比如音乐网站,当你播放了一个歌曲后,切换了页面,播放不会中断。这都是spa的好处;

后端路由:当在地址栏切换不同的ur时,都会向服务器发送一个请求,服务器响应这个请求,并在服务端拼接好html文件返回给页面来展示。 优点:减轻了前端的压力,html都由后端拼接; 缺点:依赖于网络,网速慢,用户体验很差,项目比较庞大时,服务器端压力较大,不能在地址栏输入指定的url访问相应的模块,前后端不分离。

3、既然前端路由是比较普遍的做法,那么怎么实现前端路由呢?前端路由的两种实现方式:
(1)hash模式:
hash就是一段url中的#后面的内容,hash虽然包含在url中但是不被包括在http请求中,用来指导浏览器动作,对服务器端安全无用,改变hash不会加载页面(也正是因为#后面的内容不被包含在请求中,所以对于后端来说即便没有做到对路由的全覆盖也不会出现404)。因此可以通过Onhashchange来监听路由改变从而改变相应的页面内容(可以去做ajax请求)。

(2)history模式
html5新增了两个API,history.pushState()和history.replaceState(),这两个API都会操作浏览器的历史记录堆栈,通过这种方式不会引起页面的刷新。但是这种情况下并没有向onhashchange那么好用的方法来监听url的改变,所以需要从三个角度去做控制。

history.pushState()和history.replaceState()两个方法都需要传入三个参数: history.pushState(data, null, '#/page=1'); pushState接收3个参数,第一个参数为一个obj,表示浏览器的state属性,popstate中可以拿到这个state属性来使用; 第二个参数是document.title的值,一般设定为null; 第三个参数string,用以改变当前url; 首先前端路由的改变可能由几个行为引起,所以我们要分别作不同的处理:首先我们需要维护一个url和url对应的回调函数(这个回调函数是指跳转到一个url后要做的事情,比如页面上内容的替换,ajax请求等)的映射关系

  • 当点击了a标签进行页面跳转时,那么给a标签添加一个onClick事件,事件回调中先阻止a标签的默认跳转行为,通过event.target.href获取到url,就能根据映射关系去执行相应的回调了;
  • 脚本中直接调用history.pushState()和history.replaceState()时(并不会触发onpopstate),也是通过url拿到映射的回调去执行;
  • 点击浏览器的前进、后退按钮,这里需要另一个事件onpopstate,当浏览器历史记录被激活时触发,这个事件回调可以获取到当前的url,然后根据映射关系执行回调;
    pushState接收3个参数,第一个参数为一个obj,表示浏览器的state属性,popstate中可以拿到这个state属性来使用;
    第二个参数是document.title的值,一般设定为`null`; 第三个参数string,用以改变当前url;

首先前端路由的改变可能由几个行为引起,所以我们要分别作不同的处理:首先我们需要维护一个url和url对应的回调函数(这个回调函数是指跳转到一个url后要做的事情,比如页面上内容的替换,ajax请求等)的映射关系

  • 当点击了a标签进行页面跳转时,那么给a标签添加一个onClick事件,事件回调中先阻止a标签的默认跳转行为,通过event.target.href获取到url,就能根据映射关系去执行相应的回调了;
  • 脚本中直接调用history.pushState()和history.replaceState()时(并不会触发onpopstate),也是通过url拿到映射的回调去执行;
  • 点击浏览器的前进、后退按钮,这里需要另一个事件onpopstate,当浏览器历史记录被激活时触发,这个事件回调可以获取到当前的url,然后根据映射关系执行回调;
    route1:callback1,
    route2:callback2,
    route3:callback3
};
// 监听popState事件
 window.onpopstate = function(event){
        var state = event.state;
        routeMap[state.route].call(this); 
}
function clickHandler (event){
        var route = event.target.href;
        history.pushState({route:route},null,route);
        routeMap[route].call(this);
        return false;
    }

需要注意的是,因为history模式下url与向后端发起请求的url一致,所以需要服务器端支持(做到对路由的全覆盖),将所有的url请求都指向同一个html,否则没有配置的话刷新会报404.当时做vue的项目是就出现了这种情况,刷新页面后就变为404了,因为后端没有做到对路由的全覆盖。

hash模式比较简单,但地址栏的url会有#出现,不美观; history模式,地址栏看起来会像是一个正常网站都是’/‘不会有’#’,但是需要服务器端配合做路由的全覆盖配置。