前端路由的概述和运用

一、路由的概念

在网络原理中,路由指的是分组从源到目的地时,决定端到端路径的网络范围的进程,做成硬件叫路由器,在路由器中维护着一个路由表,并根据此路由表决定下一跳的地址。在web应用中,路由实际是指根据不同的url给其分配不同的控制器(处理程序)。

二、前端路由的出现

最初在web应用开发中前端并不太关注路由,这和当时的开发方式和业务处理有关,采用的是后端模板渲染的方式。我们常看到的jsp,php都是这种方案,由后端根据url请求信息来决定响应某个页面,此时路由是在服务端配置的。这时候的路由就是url和后端服务器的交互,根据不同的路径显示不同的资源,页面也是一种资源。

这种开发方式有明显的不足,每切换一个页面都要重新加载一次,即使两个页面有很多相同的地方。还有就是前后端的代码揉杂在一起,前端要部署一个既有前端代码又有后端代码的项目,不方便本地开发调试,一旦后端代码有错误,前端无法进行开发,前端被限制在后端的开发方式中,效率很低,前端迫切的需要一种革新来改变这种开发方式。

随着前后端分离和MVVM概念的兴起及前端工程化的发展,出现了一种新的开发方式,单页应用(SPA),前端圈迅速崛起,有了爆发式的发展。单页应用的意思是只有一个页面,是无刷新的,看到的页面之间的跳转其实只是组件的切换,同时URL也要相应的变化,为了实现这种单页应用,出现了前端路由。

三、前端路由的核心实现

前端路由的核心就是URL和组件树的映射关系。因为单页应用前端整个工程实际上只有一个页面,不同的url只是在切换不同的组件,实际上就是监听url的变化然后按照他的规则来进行匹配。前端路由的实现方式主要有两种: hashhistory 模式。

1. hash模式

window.loacation.hash,url中以“#”为标识符,如:http://www.xxx/com/list.html#complete ,这个值可读可写,读取时,可以用来判断网页状态,写入时会在不重新载入网页的情况下给浏览器增加一条历史记录,有了这种特性就有了前端路由的雏形,因为改变#之后的内容相当于改变了url,但是并没有重新向服务器发送请求。JavaScript可以通过window.onhashchange来监听url变化,以实现不同组件的切换。

目前主要的路由库有vue-router,react-router,他们的主要功能是存储路由的hash以及对应的函数,然后监听hash的变化执行对应的函数。以vue-router为例,看一下他的监听源码:

 
   setupListeners () {  //设置监听器

       const router = this.router

       const expectScroll = router.options.scrollBehavior

       const supportsScroll = supportsPushState && expectScroll



       if (supportsScroll) {

         setupScroll()

       }



       window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {

         const current = this.current

         if (!ensureSlash()) {

           return

         }

         this.transitionTo(getHash(), route => {

           if (supportsScroll) {

             handleScroll(this.router, route, current, true)

           }

           if (!supportsPushState) {   // hash变化改变view

             replaceHash(route.fullPath)

           }

         })

       })

   }

这里他把hashchange是作为降级方案处理的,因为有更优的处理方式,下面会讲。这里只是设置监听的代码,当然他的前后还有一些“钩子”,即跳转前,跳转后要执行的方法,甚至有可能取消此次跳转。

2. history模式

由于html5的发布,引入了 history.pushState()history.replaceState() 方法,它们分别可以添加和修改历史记录条目。pushState需要三个参数,一个状态对象(可以通过onpopstate事件获取到),一个标题 (目前被忽略)和一个URL,replaceState参数也是一样。

通常 与window.onpopstate 配合使用,这个为前端路由的另一种模式奠定了基础,但是这种方式的url是一个完整的如http://www.xxx.com/list/complete,他每一次改变都会向服务发送一次请求资源(其实我们是没有这个页面地址的),所以需要服务器端增加一条配置,如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是我们的主页面。

下面我们用此种方法做一个简版的路由,开发思想涉及到了观察者模式,都是考虑最简单的情况。

 
<!--index.html-->

   <div class="nav" id="nav">

       <a href="javascropt:;" onclick="route.go('/')">首页</a>

       <a href="javascropt:;" onclick="route.go('/list')">列表页面</a>

       <a href="javascropt:;" onclick="route.go('/cart')">购物车页面</a>

       <a href="javascropt:;" onclick="route.go('/home')">我的</a>

   </div>

   <div id="content"></div>

   <script src="./router.js"></script>


//  router.js

class Router{

   constructor(routes){

       this.routes = {};

       this.init(routes);

       this.onPopState(); //监听popstate事件

   }  

   init(routes){  //初始化路由,并设置监听,

       let _this = this;

       Object.keys(routes).forEach((item,index,array)=>{

          _this.listen(item,routes[item]);

       });

       this.go("/"); //或个元素者取出routes对象的第一个元素

   }

   listen(url,fn){  //这里假设只有一个方法,不是方法数组添加一条

       this.routes[url] = fn;

   }

   go(url){ //触发切换事件,这里假设只有一个方法,多个方法需要循环取出并执行,并且需要处理参数情况

       history.pushState({url},null,url); //push进去一条历史记录

       this.routes[url] && this.routes[url]();

   }

   onPopState(){  //处理浏览器前进后退事件

       let _this = this;

       window.addEventListener("popstate",e=>{  

           let url = e.state && e.state.url;

           console.log(url);

           _this.routes[url]&&_this.routes[url]();

       });

   }

}

const route = new Router({  //

   "/":()=>render("首页内容"),

   "/list":()=>render("列表页内容"),

   "/cart":()=>render("购物车内容"),

   "/home":()=>render("我的内容"),

});

function render(content){

   document.getElementById("content").innerHTML = content;

}

 

总结

目前web前端路由实现的整体思路是一样的,将url映射到组件,再加上一系列的复杂情况的处理,比如说 hash模式history模式如何兼容,重定向,别名,嵌套,传参,跳转及跳转时需要提供的各种“钩子”,处理好以上各种情况就是一个完整的前端路由库了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值