Vue版本2+模拟VueRouter的history模式

news2024/11/22 13:51:38

文章目录

    • 分步骤实现
      • 创建 VueRouter 类
      • 创建静态方法,实现 install
      • 实现构造函数
      • 实现 createRouteMap
      • 实现 initComponents 方法 - router-link
      • 实现 initComponents 方法 - router-view
      • 实现 initEvents
    • 完整代码

分步骤实现

创建 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{
}

创建静态方法,实现 install

/**
 * 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的构建版本:
在这里插入图片描述
两种方式:
1、修改配置,新增 vue.config.js 配置文件,修改 runtimeCompiler: true
2、将 template 换成 render

更改为 render 函数

/**
 * 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
        })
    }
}

注意这里只是模拟一下原理,里边还有其他的条条框框的限制判断等等其他处理就不完善了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495009.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RHEL软件包管理

3.1 RHEL软件包管理 完善的软件包管理机制对于操作系统来说是非常重要的&#xff0c;没有软件包管理器&#xff0c;用户使用操作系统将会变得非常困难&#xff0c;也不利于操作系统的推广。用户要使用Linux&#xff0c;需要了解Linux的包管理机制。随着Linux的发展&#xff0…

初识Vue-数据

目录 响应式 data prop 单向数据流 Prop属性校验 计算属性&#xff08;computed&#xff09; 侦听器&#xff08;watch&#xff09; 数组操作 数组操作-解决方案 响应式 data data为什么是函数&#xff1f; 因为只有返回一个生成data的函数&#xff0c;这个组件产生的…

精妙绝伦的算法之舞:解密力扣“删除有序数组中的重复项”

本篇博客会讲解力扣“26. 删除有序数组中的重复项”这道题&#xff0c;这是题目链接。 老规矩&#xff0c;先来审题&#xff1a; 题目有对判题标准的详细解释&#xff1a; 接下来是2个示例&#xff1a; 还有提示&#xff1a; 其实这道题考察的是“去重算法”&#xff0c;即…

【Linux】基础IO_文件描述符与重定向

环境&#xff1a;centos7.6&#xff0c;腾讯云服务器Linux文章都放在了专栏&#xff1a;【Linux】欢迎支持订阅 相关文章推荐&#xff1a; 【Linux】冯.诺依曼体系结构与操作系统 【C/进阶】如何对文件进行读写&#xff08;含二进制&#xff09;操作&#xff1f; 【Linux】基础…

SuperMap GIS基础产品WebGIS FAQ集锦(2)

SuperMap GIS基础产品WebGIS FAQ集锦&#xff08;2&#xff09; 【iClient】Vue中该如何使用inject传递Map容器&#xff1f; 【解决方案】provide和inject绑定是不可响应的&#xff0c;所以传递时需要传递对象的property&#xff0c;使它变为可响应&#xff0c;示例如下&#…

为什么选择云计算

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

【python】keras包:深度学习( CNN卷积神经网络 convolution nulear network)

CNN卷积神经网络 convolution nulear network 应用场景 图像识别、根据轮廓识别的图像识别 算法逻辑 算法学得好的话&#xff0c;一眼就可以看出MLP就是暴力算法&#xff0c;时间效率低。因此希望提升效率。 剪枝方法&#xff1a; 先提取图像的关键信息&#xff08;轮廓&am…

树莓派系统配置-raspi-config

在终端内输入 sudo raspi-config 显示如下界面&#xff0c;左上方是树梅派的型号及版本信息。&#xff1a; 设置界面操作介绍 该配置工具中可以用键盘 ↑ ↓ ← → 进行选择&#xff0c;按 tab 在条目间切换&#xff0c;按 enter 确认&#xff0c;按 esc 返回。在二三级菜单…

(二)PID控制的Anti-windup

比例环节&#xff1a;快速接近目标积分环节&#xff1a;防止稳态误差微分环节&#xff1a;减少振荡 被控对象可以分为两个部分&#xff0c;分别是执行器&#xff0c;用于产生力或者能量从而改变系统&#xff0c;和处理&#xff0c;比如说温控的加热过程。在现实世界中&#xf…

PCL学习六:Filtering-滤波

参考引用 Point Cloud Library黑马机器人 | PCL-3D点云 1. 点云滤波概述 1.1 背景 在获取点云数据时&#xff0c;由于设备精度、操作者经验、环境因素等带来的影响&#xff0c;以及电磁波衍射特性、被测物体表面性质变化和数据拼接配准操作过程的影响&#xff0c;点云数据中将…

java的spi机制使用场景讲解和具体使用

八股文背多了&#xff0c;相信大家都听说过一个词&#xff0c;SPI扩展。 有的面试官就很喜欢问这个问题&#xff0c;SpringBoot的自动装配是如何实现的&#xff1f; 基本上&#xff0c;你一说是基于spring的SPI扩展机制&#xff0c;再把spring.factories文件和EnableAutoConf…

回收站文件恢复,分享4个巧妙解决方法!

案例&#xff1a;回收站文件怎么恢复 【清理电脑时一不小心清空了我的回收站&#xff0c;有朋友知道该怎么恢复吗&#xff1f;急急急&#xff01;】 回收站对于电脑用户来说&#xff0c;可以带来很多的方便&#xff0c;能让用户能够在删除文件后将其恢复。但是&#xff0c;有…

C++之正则表达式

目录 #include • .&#xff1a;换行符以外的任何字符 • […]&#xff1a;…字符中的任何一个 • [^…]&#xff1a;…字符之外的任何一个 • [[:charclass:]]&#xff1a;指定之字符类charclass中的一个 • \n, \t, \f, \r, \v&#xff1a;换行符&#xff0c;tab符号&#xf…

协程实现原理

大家好&#xff0c;我是易安&#xff01;今天我们来探讨一个问题&#xff0c;Go 协程的实现原理。此“协程”非彼”携程“。 线程实现模型 讲协程之前&#xff0c;我们先看下线程的模型。 实现线程主要有三种方式&#xff1a;轻量级进程和内核线程一对一相互映射实现的1:1线程…

自动驾驶经验分享

人生经验总结 第一个要聊的就是在自动驾驶行业工作的这几年&#xff0c;有什么人生经验可以总结一下。 我觉得从这几个方面&#xff0c;首先第一个是能力上&#xff0c;能力上你需要去锻炼&#xff0c;做成功一件事情的一个能力&#xff1b;技术上&#xff0c;对前沿的技术要…

并发编程java

1、CountDownLatch&#xff1a; 如果我们知道了我们的需要执行的任务数&#xff0c;那么我们可以用java并发包下的CountDownLatch&#xff0c;直接上代码&#xff1a; public class CountDownLaunch {private static final Executor executor Executors.newFixedThreadPool(…

SpringBoot参数校验

简单数据类型 SpringBoot自带了validation工具可以从后端对前端传来的参数进行校验&#xff0c;用法如下&#xff1a; 引入validation起步依赖 <!-- 参数校验 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>sprin…

springboot、SpringCloud 常见版本版本介绍

官方版本号&#xff08;2023年5月6日&#xff09; Spring Boot 版本说明 Spring Boot的版本号分析&#xff1a; Spring Boot的版本以数字表示。例如&#xff1a;Spring Boot 2.4.1.RELEASE --> 主版本.次版本.增量版本&#xff08;Bug修复&#xff09; 主版本&#xff0c…

学系统集成项目管理工程师(中项)系列18a_进度管理(上)

1. 规划项目进度管理 1.1. 为实施项目进度管理制定政策、程序&#xff0c;并形成文档化的项目进度管理计划的过程 1.2. 输入 1.2.1. 项目管理计划 1.2.1.1. 范围基准 1.2.1.2. 其他信息 1.2.2. 项目章程 1.2.2.1. 【19下选43】 1.2.2.2. 项目章程中规定的项目审批要求和总…

python ---->>利用 urllib 库获取网络资源

我的个人博客主页&#xff1a;如果’真能转义1️⃣说1️⃣的博客主页 &#xff08;1&#xff09;关于Python基本语法学习---->可以参考我的这篇博客《我在VScode学Python》 &#xff08;2&#xff09;pip是必须的在我们学习python这门语言的过程中Python ----&#xff1e;&a…