首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【手撕Vue-Router】-实现router-view

【手撕Vue-Router】-实现router-view

原创
作者头像
BNTang
发布2023-11-30 13:15:11
2250
发布2023-11-30 13:15:11
举报

前言

在上一篇 [手撕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技术和一些个人的见解,谢谢大家的支持。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 实现思路
  • 实现代码
  • 解决方案
  • 总结
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档