大前端【3-1-1笔记】手写Vue Router

1、Hash模式与History模式

二者的存在表现形式和原理上的区别

1、表现形式的区别

Hash:https://api.aibianxian.net/igameh5/#/detail/213?token=123,链接中带有#号

History: https://api.aibianxian.net/igameh5/detail/213/123

2、原理区别

Hash:基于锚点,以及onHashChange事件,通过锚点的值作为路由地址,当地址发生变化后,触发onHashChange事件,然后根据路径决定页面呈现的内容。

**History:**基于HTML5中的HistoryAPI

  • history.pushState() 存在兼容模式,IE10以后才支持
  • history.replaceState()

pushState与push方法的区别是:调用push的时候路径会发生变化,会向服务器发送请求,调用pushState的时候,不会向服务器发送请求,只会改变地址栏中的地址,并且将地址记录到历史记录中,可以实现客户端路由

3、History模式的使用
  • History需要服务器的支持
  • 单页应用中,服务端不存在某一个地址,会返回404页面
  • 在服务端应该除了静态资源外都返回单页应用的index.html

2、Vue的构建版本

运行时版本和完整版

1、运行时版本

不支持template模板,需要打包的时候提前编译。可以使用render函数。vue-cli创建的项目默认是运行时版本,因为效率更高

Vue.component('router-link',{
            props:{
                to:String
            },
            render(h){
                return h('a',{
                    attrs:{
                        href:this.to
                    }
                },[this.$slots.default])
            }
 })
2、完整版

包含运行时编译器runtimeCompiler,体积比运行时版大10K左右,程序运行的时候会把模板转换为render函数,性能不如运行时版本。

3、手写Vue Router

配置文件

1、vue.config.js
module.exports = {
    //加载完整版本的vue
    runtimeCompiler:true
}
2、index.js
// index.js
let _Vue = null
export default class VueRouter {
    static install(Vue) {
        // 1、判断当前插件是否已经被安装
        if (VueRouter.install.installed) {
            return
        }
        VueRouter.install.installed = true
        //2、把Vue构造函数记录到全局变量
        _Vue = Vue
        //3、把创建Vue实例时候传入的router对象注册到Vue实例上
        _Vue.mixin({
            beforeCreate() {
                console.log(this.$options)
                if (this.$options.router) {
                    console.log(123)
                    _Vue.prototype.$router = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }

    constructor(options) {
        this.options = options
        this.routerMap = {}
        this.data = _Vue.observable({
            current: "/"
        })
    }

    init() {
        this.createRouteMap()
        this.initCommponents(_Vue)
        this.initEvent()
    }

    createRouteMap() {
        //作用:遍历所有的路由规则,将其解析为键值对存储到routeMap中
        this.options.routes.forEach(route => {
            this.routerMap[route.path] = route.component
        })
    }

    initCommponents(Vue) {
        console.log("注册")
    
         // Vue.component('router-link', {
        //     props: {
        //         to: String
        //     },
        //     template: ''
        // })


        //运行时版本使用
        Vue.component('router-link',{
            props:{
                to:String
            },
            render(h){
                return h('a',{
                    attrs:{
                        href:this.to
                    },
                    on:{
                        click: this.clickHandler
                    }
                },[this.$slots.default])
            },
            methods:{
                clickHandler(e){
                    //修改路徑
                    history.pushState({},'',this.to)
                    //
                    this.$router.data.current = this.to
                    e.preventDefault()
                }
            }
        })
       
        const self = this
        Vue.component('router-view',{
            render(h){
                const component = self.routerMap[self.data.current]
                return h(component)
            }
        })
    }

    //当我们前进或者后退的时候,没有重新加载组件,所以
    initEvent(){
        //popstate当历史发生变化的时候触发,调用pullState,replaState不会触发
        window.addEventListener('popstate',()=>{
            this.data.current = window.location.pathname
        })
    }
}

你可能感兴趣的:(webpack,拉钩教育,vue)