手撕Vue-Router-实现router-view

前言
在上一篇 [手撕Vue-Router-实现router-link] 中,我们实现了 router-link 组件,这一篇我们来实现 router-view 组件。
实现思路
router-view 其实与 router-link 是同一个世界,同一个梦想的,那么我就废话不多说了,直接上代码。
实现代码
回到我们的 NueRouter.install 方法中,直接编写 Vue.component('router-view', {}),这里我们直接使用了 Vue.component 方法,这个方法是 Vue 内部提供的,用于注册全局组件的方法。
Vue.component('router-view', {});
注册好了全局组件之后我们就可以使用这个组件了,我们在 App.vue 中使用这个组件。

接下来我们要做的事情就是根据 router-link 中的 to 属性,来获取对应的组件,然后渲染到 router-view 中。
那么怎么渲染呢?我们可以使用 render 函数来渲染,render 函数是 Vue 内部提供的,用于渲染组件的函数。render 函数接收一个 h 函数作为参数,h 函数用于渲染组件。
代码如下:
Vue.component('router-view', {
    render(h) {
        return h();
    }
});
那么我们就可以在 h 函数中,根据路由地址来获取对应的组件,然后渲染到 router-view 中。
那么问题就来了我们拿到对应的组件呢?首先我们需要获取到路由信息,然后在拿到当前的路由地址,然后拿到当前的路由地址,去我提取的路由信息中,找到对应的组件。
好了,我们知道了我们要做什么,那么我们就开始做吧。
首先我们需要获取到路由信息,我们可以通过 const routesMap = this._self.$router.routesMap; 来获取到路由信息。
然后我们需要获取到当前的路由地址,我们可以通过 const currentPath = this._self.$route.currentPath 来获取到当前的路由地址。
然后我们就可以通过 routesMap[currentPath] 来获取到对应的组件了。
那么我们就可以在 h 函数中,根据路由地址来获取对应的组件,然后渲染到 router-view 中。
代码如下:
Vue.component('router-view', {
    render(h) {
        const routesMap = this._self.$router.routesMap;
        const currentPath = this._self.$route.currentPath;
        const currentComponent = routesMap[currentPath];
        return h(currentComponent);
    }
});
好了,我们的 router-view 组件就实现了,我们来看一下效果。浏览器自行测试。
我在测试过程中,我点击了 首页 和 关于 两个按钮,发现并没有渲染出对应的组件,这是为什么呢?并不是我们的代码有问题,而是在渲染网页的时候,首先它会先渲染组件,然后再执行 load 事件,所以就导致了我们在渲染组件的时候,我们还没有保存 currentPath,因为 currentPath 是在 load 事件中保存的,所以我们在渲染组件的时候,是获取不到 currentPath 的,怎么验证这个问题呢?我们可以在 load 打印一个内容,然后在 render 中,也打印一下 内容,并且将 currentPath 也打印出来,我们就可以看到这个问题了。

打开浏览器,点击首页按钮,控制台打印如下:

可以看到,我们在渲染组件的时候,currentPath 是 null,这就是我们的问题所在。
解决方案
那么我们怎么解决这个问题呢?其实很简单,我们只需要监听 currentPath 的变化,然后在 currentPath 变化的时候,重新渲染组件就可以了。
那么怎么让 currentPath 变化之后,重新渲染组件呢?默认情况下 Vue 是双向数据绑定的,默认情况下只要数据发生变化,就会重新渲染组件。
但是有一个前提条件,就是数据必须是响应式的(也就是说 currentPath 是一个双向绑定的数据),那么怎么让 currentPath 变成一个响应式的数据呢?其实可以在我们往 Vue 实例中添加 $router or $route 的时候,将 currentPath 变成一个响应式的数据。
那么怎么将 currentPath 变成一个响应式的数据呢?我们可以使用 Vue 内部提供的 Vue.util.defineReactive 方法,这个方法可以将一个普通的数据变成一个响应式的数据。
那么我们就可以在我们往 Vue 实例中添加 $router or $route 的时候,将 currentPath 变成一个响应式的数据。
代码如下:
Vue.util.defineReactive(this, 'xxx', this.$router);

好了,我们的 currentPath 变成了一个响应式的数据,那么我们就可以在 currentPath 变化的时候,重新渲染组件了。
我们的 router-view 组件就实现了。浏览器自行测试。
总结
主要就是使用 Vue.component 方法来注册全局组件,然后使用 render 函数来渲染组件,然后在 h 函数中,根据路由地址来获取对应的组件,然后渲染到 router-view 中。
还有就是在渲染组件的时候,currentPath 是 null,因为而是在渲染网页的时候,首先它会先渲染组件,然后再执行 load 事件,所以就导致了我们在渲染组件的时根据 currentPath 获取不到对应的组件。
解决方案就是将 currentPath 变成一个响应式的数据,默认情况下 Vue 是双向数据绑定的,默认情况下只要数据发生变化,就会重新渲染组件, 这样一来就达到了我们的目的。
最后
大家好我是 BNTang, 一个热爱分享的技术的开发者,如果大家觉得我的文章对你有帮助的话,可以关注我的公众号 JavaBoyL,我会在公众号中分享一些IT技术和一些个人的见解,谢谢大家的支持。

手撕Vue-Router-实现router-view的更多相关文章
- Vue 组件之 Router
		
Vue 组件之 Router Vue 开发单页应用的时候,免不了使用Vue组件.在单页应用上如何进行组件切换? 结构如下图所示: 主页面包含Foo组件与Bar组件,在主页面中可以进行Foo与 Bar的 ...
 - vue路由请求 router
		
创建一个Router.js文件 // 路由请求//声明一个常量设置路菜单// import Vue from "vue/types/index";import Vue from ' ...
 - vue学习之router
		
路由文档:https://router.vuejs.org/zh/guide/ 使用vue做spa应用的话,一定会涉及到路由. 安装 安装router插件 npm install vue-router ...
 - vue项目中router路由配置
		
介绍 路由:控制组件之间的跳转,不会实现请求.不用页面刷新,直接跳转-切换组件>>> 安装 本地环境安装路由插件vue-router: cnpm install vue-rou ...
 - vue中使用router全局守卫实现页面拦截
		
一.背景 在vue项目中使用vue-router做页面跳转时,路由的方式有两种,一种是静态路由,另一种是动态路由.而要实现对路由的控制需要使用vuex和router全局守卫进行判断拦截(安全问题文章最 ...
 - Vue的路由Router之导航钩子和元数据及匹配
		
一.文件结构 二.vue.js 打开此链接 https://cdn.bootcss.com/vue/2.6.10/vue.js 复制粘贴页面的所有内容 三.vue-router.js 打开此链接 h ...
 - vue全家桶router、vuex、axios
		
main.js import Vue from 'vue' import App from './App' import router from './router' import store fro ...
 - vue & vue router & dynamic router
		
vue & vue router & dynamic router https://router.vuejs.org/guide/essentials/dynamic-matching ...
 - 【面试题】Vue中的$router 和 $route的区别
		
Vue中的$router 和 $route的区别 点击视频讲解更加详细 this.$route:当前激活的路由的信息对象.每个对象都是局部的,可以获取当前路由的 path, name, params, ...
 - 手写vue路由
		
目录 一.简易demo 二.Vue-Router传参方式 三.进阶-路由导航 一.简易demo // routes注册 import Vue from "vue"; // impo ...
 
随机推荐
- 【docker】运维相关名词 Iaas-Paas和Saas  docker镜像设置 启动与停止常用命令 镜像相关命令 容器相关命令
			
目录 上节回顾 今日内容 1 什么是Iaas-Paas和Saas 2 docker 启动设置镜像 2.1 启动与停止常用命令 3 镜像相关命令 4 容器相关命令 练习 上节回顾 # 1 flask-s ...
 - BOM批量查询
			
1业务要求 1.当多层展开时: 根据"BOM应用程序"字段CAPID在TC04中取出"选择ID"TC04-CSLID: 再根据TCS41-CSLID= TC0 ...
 - 【Cxx 20】使用 std::span 代替数组指针传参
			
我们知道std::string_view可以创建std::string的一个视图,视图本身并不拥有实例,它只是保持视图映射的状态.在不修改实例的情况下,使用std::string_view会让字符串处 ...
 - 解决SUM函数返回为NULL
			
解决SUM函数返回为NULL SUM函数的作用:计算某一字段中所有行的数值和, 使用SUM函数进行对符合条件的结果行数进行求和. 问题产生: sum 求和时会对 null 进行过滤,不计算,但如果没有 ...
 - 定向减免!函数计算让 ETL 数据加工更简单
			
业内较为常见的高频短时 ETL 数据加工场景,即频率高时延短,一般费用大头均在函数调用次数上,推荐方案一般为攒批处理,高额的计算成本往往令用户感到头疼,函数计算推出定向减免方案,让 ETL数据加工更简 ...
 - 十一、docker的容器互联
			
系列导航 一.docker入门(概念) 二.docker的安装和镜像管理 三.docker容器的常用命令 四.容器的网络访问 五.容器端口转发 六.docker数据卷 七.手动制作docker镜像 八 ...
 - element-china-area-data
			
https://blog.csdn.net/xiejnpeng/article/details/111400199
 - C# 双向链表的实现
			
类数据 public class Objects { private int number; /**//* 货物编号 */ private string name; /**//* 货物名称 */ pr ...
 - Java应用架构演变史
			
垂直应用架构 也叫单体架构.以 MVC 的垂直架构举例,MVC 架构通常分为 3 层,展示层.控制层.模型层.通常基于 MVC 架构开发的应用代码会打成一个 war 包,部署在 Tomcat 等 We ...
 - 使用zipFile读取文件时遇到的问题及解决(KeyError: "There is no item named 'xxx' in the archive")
			
问题描述 在Windows上跑一段代码时,遇到如下问题: KeyError: "There is no item named 'CDR_Data\\\\CDR.Corpus.v010516\ ...