Vue バージョン 2 以降は、VueRouter の履歴モードをシミュレートします。

一歩ずつ

VueRouterクラスを作成する

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

export default class VueRouter{
    
    
}

静的メソッドを作成してインストールを実装する

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                }
            }
        })
    }
}

コンストラクターを実装する

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                }
            }
        })
    }
    constructor(options){
    
    
        this.options = options
        this.routeMap = {
    
    }
        // 将 current 注册为响应式对象
        this.data = _Vue.observable({
    
     
            current: '/'
        })
    }
}

createRouteMapを実装する

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                }
            }
        })
    }
    constructor(options){
    
    
        this.options = options
        this.routeMap = {
    
    }
        // 将 current 注册为响应式对象
        this.data = _Vue.observable({
    
     
            current: '/'
        })
    }
    
    createRouteMap(){
    
    
        // 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
        this.options.routes.forEach(route=>{
    
    
            this.routeMap[route.path] = route.component
        })
    }
}

initComponents メソッドの実装 - router-link

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }
    constructor(options){
    
    
        this.options = options
        this.routeMap = {
    
    }
        // 将 current 注册为响应式对象
        this.data = _Vue.observable({
    
     
            current: '/'
        })
    }

    init(){
    
    
        this.createRouteMap()
        this.initComponents(_Vue)
    }
    
    createRouteMap(){
    
    
        // 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
        this.options.routes.forEach(route=>{
    
    
            this.routeMap[route.path] = route.component
        })
    }

    initComponents(Vue){
    
    
        const self = this
        Vue.component('route-link', {
    
    
            props: {
    
    
                to: String
            },
            template: '<a :href="to"><slot></slot></a>'
        })
    }
}

問題が発生します:you are using the runtime-only build of Vue where the template compiler is not avriable. ...

router-view のエラー レポートもありますが、router-view コンポーネントは定義されていませんので、心配する必要はありません。

Vue ビルド バージョン:
ここに画像の説明を挿入
2 つの方法:
1. 構成を変更し、vue.config.js 構成ファイルを追加し、変更します。runtimeCompiler: true
2. テンプレートをレンダリングに置き換えます。

レンダリング機能への変更

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }
    constructor(options){
    
    
        this.options = options
        this.routeMap = {
    
    }
        // 将 current 注册为响应式对象
        this.data = _Vue.observable({
    
     
            current: '/'
        })
    }

    init(){
    
    
        this.createRouteMap()
        this.initComponents(_Vue)
    }
    
    createRouteMap(){
    
    
        // 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
        this.options.routes.forEach(route=>{
    
    
            this.routeMap[route.path] = route.component
        })
    }

    initComponents(Vue){
    
    
        const self = this
        Vue.component('route-link', {
    
    
            props: {
    
    
                to: String
            },
            render(h){
    
    
                return h('a', {
    
    
                    attrs: {
    
    
                        href: this.to
                    },
                }, [this.$slots.default])
            },
            // template: '<a :href="to"><slot></slot></a>'
        })
    }
}

initComponents メソッドの実装 - router-view

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }
    constructor(options){
    
    
        this.options = options
        this.routeMap = {
    
    }
        // 将 current 注册为响应式对象
        this.data = _Vue.observable({
    
     
            current: '/'
        })
    }

    init(){
    
    
        this.createRouteMap()
        this.initComponents(_Vue)
    }
    
    createRouteMap(){
    
    
        // 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
        this.options.routes.forEach(route=>{
    
    
            this.routeMap[route.path] = route.component
        })
    }

    initComponents(Vue){
    
    
        const self = this
        Vue.component('route-link', {
    
    
            props: {
    
    
                to: String
            },
            render(h){
    
    
                return h('a', {
    
    
                    attrs: {
    
    
                        href: this.to
                    },
                    on: {
    
    
                        click: this.clickHandler
                    } 
                }, [this.$slots.default])
            },
            methods: {
    
    
                clickHandler(e){
    
    
                    // 取消默认行为
                    e.preventDefault()
                    // pushState 改变地址栏,但是不向服务器发送请求
                    history.pushState({
    
    }, '', this.to)
                    // 当前路径记录到 current 里边
                    this.$router.data.current = this.to
                }
            }
            // template: '<a :href="to"><slot></slot></a>'
        })
        
        Vue.component('router-view',{
    
    
            // 由于 current 是响应式的,所以这里会自动渲染对应的组件
            render(h){
    
    
                const component = self.routeMap[self.data.current]
                return h(component)
            }
        })
    }
}

initEventsを実装する

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }
    constructor(options){
    
    
        this.options = options
        this.routeMap = {
    
    }
        // 将 current 注册为响应式对象
        this.data = _Vue.observable({
    
     
            current: '/'
        })
    }

    init(){
    
    
        this.createRouteMap()
        this.initComponents(_Vue)
        this.initEvent()
    }
    
    createRouteMap(){
    
    
        // 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
        this.options.routes.forEach(route=>{
    
    
            this.routeMap[route.path] = route.component
        })
    }

    initComponents(Vue){
    
    
        const self = this
        Vue.component('route-link', {
    
    
            props: {
    
    
                to: String
            },
            render(h){
    
    
                return h('a', {
    
    
                    attrs: {
    
    
                        href: this.to
                    },
                    on: {
    
    
                        click: this.clickHandler
                    } 
                }, [this.$slots.default])
            },
            methods: {
    
    
                clickHandler(e){
    
    
                    // 取消默认行为
                    e.preventDefault()
                    // pushState 改变地址栏,但是不向服务器发送请求
                    history.pushState({
    
    }, '', this.to)
                    // 当前路径记录到 current 里边
                    this.$router.data.current = this.to
                }
            }
            // template: '<a :href="to"><slot></slot></a>'
        })
        
        Vue.component('router-view',{
    
    
            // 由于 current 是响应式的,所以这里会自动渲染对应的组件
            render(h){
    
    
                const component = self.routeMap[self.data.current]
                return h(component)
            }
        })
    }

    initEvent(){
    
    
        // 点击浏览器的前进后退按钮触发
        window.addEventListener('popstate', ()=>{
    
    
            this.data.current = window.location.pathname
        })
    }
}

完全なコード

/**
 * VueRouter Class
 * -------------------------------------
 * + options
 * + data
 * + routeMap
 * -------------------------------------
 * + Constructor(Option): VueRouter
 * _install(Vue): void
 * + init(): void
 * + initEvent: void
 * + CreateRouteMap(): void
 * + initComponents(Vue): void
 */

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(){
    
    
                // router 执行,组件不执行
                if(this.$options.router){
    
    
                    _Vue.prototype.$router = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }
    constructor(options){
    
    
        this.options = options
        this.routeMap = {
    
    }
        // 将 current 注册为响应式对象
        this.data = _Vue.observable({
    
     
            current: '/'
        })
    }

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

    createRouteMap(){
    
    
        // 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
        this.options.routes.forEach(route=>{
    
    
            this.routeMap[route.path] = route.component
        })
    }

    initComponents(Vue){
    
    
        const self = this
        Vue.component('route-link', {
    
    
            props: {
    
    
                to: String
            },
            render(h){
    
    
                return h('a', {
    
    
                    attrs: {
    
    
                        href: this.to
                    },
                    on: {
    
    
                        click: this.clickHandler
                    } 
                }, [this.$slots.default])
            },
            methods: {
    
    
                clickHandler(e){
    
    
                    // 取消默认行为
                    e.preventDefault()
                    // pushState 改变地址栏,但是不向服务器发送请求
                    history.pushState({
    
    }, '', this.to)
                    // 当前路径记录到 current 里边
                    this.$router.data.current = this.to
                }
            }
            // template: '<a :href="to"><slot></slot></a>'
        })
        Vue.component('router-view',{
    
    
            // 由于 current 是响应式的,所以这里会自动渲染对应的组件
            render(h){
    
    
                const component = self.routeMap[self.data.current]
                return h(component)
            }
        })
    }

    initEvent(){
    
    
        // 点击浏览器的前进后退按钮触发
        window.addEventListener('popstate', ()=>{
    
    
            this.data.current = window.location.pathname
        })
    }
}

なお、これは原理をシミュレーションしたものであり、内部には他の制約や判定があり、その他の処理も完璧ではありません。

おすすめ

転載: blog.csdn.net/qq_38652871/article/details/130511306