Vue-router中hash模式和history模式

一、路由

1.前端路由

  • Hash:使用url中的hash(#后面的参数)来作为路由,通过监听hash变化找到对应组件中内容更新到页面中去。支持所有浏览器。
  • History:使用HTML5 History API 和服务器配置。参考官网中HTML5 History模式。有兼容性,支持特定浏览器。

2.后端路由

  • 直接访问url,向服务器请求资源。

3.前后端路由区别

  • 后端路由向服务器发出请求。
  • 前端路由修改视图时,不会向服务器发出请求。
二、hash模式和history模式的区别

1.hash

  • 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:http://www.baidu.com/#/hello,hash 的值为 #/hello。利用 location.hash和window.addEventListener('hashchange,()=>{})方法获取和监听hash值。它的特点在于:hash 虽然出现在 URL 中,修改hash不会向服务器发送http请求,因此改变 hash 不会重新加载页面。
  • 符号#夹杂在 URL 里看起来确实有些不太美丽
  • 兼容性好,所有浏览器都支持
  • hash 只可添加短字符串
  • hash 模式下,仅 hash 符号之前的内容会被包含在请求中,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误

2.history

  • 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
  • 没有符号#,看起来优雅很多。
  • 兼容指定浏览器。
  • pushState() 通过 stateObject 参数可以添加任意类型的数据到记录中
  • 用户手动输入 URL 后回车,或者刷新(重启)浏览器的时候跳转后刷新或者回跳,会报一个404的错误,找不到指定的路由,所以后端将所有请求都强制重定向到首页,相当于服务端屏蔽了访问资源不存在的情况,而将路由的工作留给客户端自己去处理,这样启用了history模式的前端路由在直接定位到子页面时就不会报错了。
  • 当服务端重定向后,如果没有进行SSR的同构路由定制,对于所有路由请求都会返回index.html页面,此时如果需要使用404页面,就需要在客户端路由中设定一个优先级最低的兜底路由,由于优先级的缘故,它不会影响其他精确匹配的路由配置:
const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})
三、实现一个简单hash路由(没有支持子路由哦~)
class HistoryRoute{
    constructor(){
        this.current=null
    }
}
class vueRouter{
    constructor(options){
        this.mode=options.mode||'hash';
        this.routes=options.routes||[];
        this.routesMap=this.createMap(this.routes);
        this.history=new HistoryRoute;
        this.init();
    }
    init(){//获取当前current路径
        if(this.mode=='hash'){
            //自动加#
            location.hash?'':location.hash='/'
        }
        window.addEventListener('load',()=>{
            this.history.current=location.hash.slice(1)//获取#后面值
        })
        window.addEventListener('hashchange',()=>{//监听hash改变
            this.history.current=location.hash.slice(1)
        })
    }
        //将routes中路径和组件以键值对关联起来
    createMap(routes){
        return routes.reduce((memo,current)=>{
            memo[current.path]=current.component
            return memo
        },{})
    }
}
vueRouter.install=function(Vue){
    if(vueRouter.install.installed)return //判断插件是否已注册
    vueRouter.install.installed=true
    Vue.mixin({
        beforeCreate(){//实现双向数据绑定
            if(this.$options && this.$options.router){
                this._root=this
                this._router=this.$options.router;
                Vue.util.defineReactive(this,'current',this._router.history)
            }else{
                this._root=this.$parent._root
            }
            //$router不可修改
            Object.defineProperty(this,"$router",{
                get(){
                    return this._root._router;
                },
            })
            
        },
    })
    Vue.component('router-view',{//注册组件
        render(h){
            console.log(this._self)
            var current=this._self._root._router.history.current
            var routesMap=this._self._root._router.routesMap
            return h(routesMap[current])//渲染组件
        }
    })
}
export default vueRouter;
四、总结
  • hash 模式和 history 模式都属于浏览器自身的特性,Vue-Router 只是利用了这两个特性(通过调用浏览器提供的接口)结合注册Vue全局插件、注册Vue全局组件(router-view)等技术来实现前端路由。对于一般的 Vue + Vue-Router + Webpack + XXX 形式的 Web 开发场景,用 history 模式即可,只需在后端(Apache 或 Nginx)进行简单的路由配置,同时搭配前端路由的 404 页面支持,毕竟以美为主嘛,哈哈~。

你可能感兴趣的:(Vue-router中hash模式和history模式)