vue-router 的两种模式和原理

472 阅读2分钟

router

什么是router

router是伴随spa单页面应用产生的一种页面挑战实现方案,在此之前页面的跳转是通过服务器端进行控制的。 传统的页面跳转: 通过前端向后台发送请求,后端通过渲染引擎的模板,数据嵌入模板,然后返回完整的html页面,实现方式有a标签的跳转,form表单提交,js动态调用window.href h5中的historyd的go forward back。 spa页面跳转: 通过浏览器的劫持 来进行页面的跳转,以及对于数据的请求,spa实现拦截有两种方式hash和history

hash模式

运用hashchange事件的方式进行地址栏的拦截 对应的不同hash则访问的不同页面

  class CreateRoute{
     constructor(){
         this.routes={}
         this.refresh=this.refresh.bind(this)
         //初级进来刷新
         window.addEventListener('load', this.refresh);
         //监听hash的改变
         window.addEventListener('hashchange',this.refresh)
     }
     route(path,callback){
         this.routes[path]=callback || function(){} 
     }
     refresh(){
         const href=`/${window.location.hash.slice(1)}`
         console.log(href,this.routes)
         this.routes[href]()
     }
   }
    
    const Route=new CreateRoute()
    Route.route('/about', () => changeText("关于我们页面"));
    Route.route('/user', () => changeText("用户列表页"));
    Route.route('/', () => changeText("首页"));

    function changeText(arg) {
        document.getElementById('context').innerHTML = arg;
    }

history

利用pushState和replaceState两种方法操作地址栏 不会发送请求的现象,地址栏不会进行刷新的方式去实现路由的跳转,但是前进和后端会触发popstate的事件

   class createRouter{
      
       constructor(){
        this.routers={}
        this.currentPath=''
        this.handlePopState=this.handlePopState.bind(this)
        this._init=this._init.bind(this)
        window.addEventListener('popstate',this.handlePopState)
       window.addEventListener('load',this._init(this.currentPath))
       }
       _init(path){
        console.log(path,this.routers)
        window.history.replaceState({path},null,path)
        const cb = this.routers[path]
      
        if(cb){
            cb()
        }
       }
       go(path){
        this.currentPath=path
           //入栈 
          window.history.pushState({path},null,path)
        //调用回调
        const cb = this.routers[path]
        if(cb){
            cb()
        }
       }
    
      handlePopState(e){

       const path=e.state&&e.state.path
       this.routers&&this.routers[path]()
      }    
       route(path,callback){
        this.routers[path]=callback
       }
    }
    const Route = new createRouter()
     Route.route('./about', () => changeText("关于我们页面"));
    Route.route('./user', () => changeText("用户列表页"));
    Route.route('./', () => changeText("首页"));

    function changeText(arg) {
        document.getElementById('context').innerHTML = arg;
    }
    container.addEventListener('click' , e => {
        if(e.target.tagName === 'A') {
            e.preventDefault();
            Route.go(e.target.getAttribute('href'))
        }
    })

hash和history路由的区别

相同点:hash和history都是基于spa应用实现的前端页面切换方式.页面的控制跳转都发生在前端。 区别: 1.hash地址栏中带有# history地址栏则没有 2.hash不利于seo或者ssr 3.hash不需要服务器端的支持,自身就可以完成页面的跳转和加载,history需要服务端的支持,需要服务端配置首页 然后首页根据路劲再进行跳转,配置404页面的重定向index.html页面 然后走路由 (刷新的时候地址栏发送的请求不是真是存在的请求,会出现404 因此服务端需要返回index.html 再index.html 走路由配置获取对应的页面)

vue-router 源码图

image.png