vue-router的本质: 路由就是SPA(单页应用)的路径管理器,vue-router的单页应用中,则是路径之间的切换,也就是组件的切换,路由模块的本质就是建立起url和页面之间的映射关系
为什么不能用a标签,这是因为Vue左的是单页应用,当你的项目准备打包时,会生成dist文件夹,这里面只有静态资源和一个index.html页面,所有a标签跳转页面不起作用
单页应用的核心之一就是:更新视图而不重新请求页面,vue-router在实现单页面前端路由时 ,提供两种方式:Hash模式和History模式,根据mode参数来决定使用哪一种
Hash模式 vue-router默认hash模式,使用URL的hash模拟一个完整的URL,于是URL改变时,页面不会重新加载,hash(#)是URL的锚点,代表网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载页面,也就是hash出现在URL中(#后面的值),但不会被包含在http请求中,对后端没有影响,因此改变hash不会重新加载页面;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用“后退”按钮,就可以回到上一个位置,所以Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据,hash模式原理是onhashchange事件(监测hash值变化),可以在window对象上监听这个事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 class Router { constructor ( ) { this .routes={}; this .currentUrl="" ; this .history=[]; this .currentIndex=this .history.length-1 ; this .refresh=this .refresh.bind(this ); this .backoff=this .backoff.bind(this ) this .isBack=false window .addEventListener('load' ,this .refresh,false ) window .addEventListener('hashchange' ,this .refresh,false ) } route (path,callback ) { this .routes[path]=callback||function ( ) {} } refresh ( ) { this .currentUrl=location.hash.slice(1 )||'/' ; if (!this .isBack){ if (this .currentIndex<this .history.length-1 ){ this .history=this .history.slice(0 ,this .currentIndex+1 ) } this .history.push(this .currentUrl) this .currentIndex++; } this .routes[this .currentUrl]() this .isBack=false ; } backoff ( ) { this .isBack=true this .currentIndex<=0 ?(this .currentIndex=0 ) :(this .currentIndex=this .currentIndex-1 ) location.hash=`#${this .history[this .currentIndex]} ` this .routes[this .history[this .currentIndex]] } } window .Router=new Routers()const content=document .querySelector('body' )const button=document .querySelector('button' )function changeBgColor (color ) { content.style.background=color } Router.route('/blue' ,function ( ) { changeBgColor('blue' ) }) Router.route('/green' ,function ( ) { changeBgColor('green' ) }) Router.route('/red' ,function ( ) { changeBgColor('red' ) }) button.addEventListener('click' ,Router.backoff,false )
history模式 hash模式在url中自带#,比较丑,可以用路由的history模式,只需要在配置路由规则时,加上’mode:history’
这种模式利用了html5 history Interface中新增的pushState()和replaceState()方法 ,这两个方法应用于浏览器记录栈,在当前已有的back,forwarc,go基础上,它们提供了对历史记录修改的功能,只是当修改时,虽然改变了当前的URL,但浏览器不会去请求服务器该路径下的资源, 一旦刷新就会暴露,显示404,因此这种模式下需要后端的支持,在服务端增加一个覆盖所有情况的候选资源:如果URL匹配不到任何静态资源,就返回一个Index.html页面,这个页面就是app依赖的页面
export const routes=[
{path:”*”,redirect:’/‘}
]
history.pushState用于在浏览器中添加历史记录,但不触发跳转,此方法接收三个参数:
state:一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数,不需要这个对象时此处就填null
title:新页面标题,但是所有浏览器目前都忽略这个值,因此这里填null
url:新的网址,必须与当前页面处在同一个域,浏览器的地址栏将显示这个网址
新标准下路由的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Router { constructor ( ) { this .routes={}; this .bindPopState(); } init (path ) { history.replaceState({path :path},null ,path) this .routes[path]&&this .routes[path]() } route (path,callback ) { this .routes[path]=callback||function ( ) {} } go (path ) { history.pushState({path :path},null ,path) this .routes[path]&&this .routes[path]() } _bindPopState ( ) { window .addEventListener('popstate' ,e => { const path=e.state&&e.state.path; this .routes[path]&&this .routes[path]() }) } } window .Router = new Routers();Router.init(location.pathname); const content = document .querySelector('body' );const ul = document .querySelector('ul' );function changeBgColor (color ) { content.style.backgroundColor = color; } Router.route('/' , function ( ) { changeBgColor('yellow' ); }); Router.route('/blue' , function ( ) { changeBgColor('blue' ); }); Router.route('/green' , function ( ) { changeBgColor('green' ); });