网站首页 > 技术文章 正文
上篇说了vue-router的基本概念,这篇写下路由嵌套,还是一篇一个问题。
vue-router的思路
在vue-router的理念中,<router-view>是一个舞台,某个时刻只能渲染一个组件。这个容易理解,比如舞台上唱歌,一次只能一个人表演。具体的代码在上个例子中有比较详细的说明,现在看另一个问题,如下:
当组件B上台时,它内部也有一个router-view,这样app一共就有两个router-view。但是组件B的<router-view>只是给它的子组件找个出口,就好比一个部门内部还有一个表演场所,只供内部人员使用。
现在提出的问题是:为什么组件B-2渲染时,它不会跑到最外层的<router-view>而是在父组件的<router-view>中?刚接触这个东西的时候,我就很好奇这个问题。
vue-router源码解读
当解析组件的子菜单路由时,实际上已经形成了一个链式关系,最主要的一个字段就是parent,如下所示:
parent关系确定之后,接下再创建一个匹配项,是什么意思呢?
就是凡是和当前的路由项有关系的祖先,都被加入进来,比如对于/test/a来说,它的匹配项如下:
//伪码
['/test','/test/a']
假如嵌套的很深,如下:
//伪码
['/test','/test/a','/test/a/b',
'/test/a/b/c'....]
总结:1、首先确定parent关系。是通过children递归得到的。2、确定match关系,是通过parent的链递归得到的。
开始渲染
当vue渲染app时,它内部有两层的router-view,那么每一层该渲染哪个组件呢?
<router-view>是一个组件,它有一个明确的render函数,在vue-router中有定义,我们进到源代码中,可以看到如下:
while (parent && parent._routerRoot !== parent) {
var vnodeData = parent.$vnode ? parent.$vnode.data : {};
if (vnodeData.routerView) {
depth++;
}
if (vnodeData.keepAlive && parent._directInactive && parent._inactive) {
inactive = true;
}
parent = parent.$parent;
}
data.routerViewDepth = depth;
在渲染之前,我们需要知道route已经确定了,也就是路由路径确定了,而route的matched也确定了。那么就根据router-view的parent计算view是第几层(从0开始),也就是深度,然后通过深度得到matched中的值。
比如渲染第一个router-view时,得到深度为0,就渲染/test组件。在渲染/test组件的过程中,又遇到一个<router-view>于是,计算它的深度为1,那么就取matched下标为1的位置,得到/test/a的组件。
总起来说就是,任何一个路由,不仅仅是把自身的组件规定好,而是整个app的所有<router-view>都规定好了,比如说,当我们定向到/test/a路由时,它把整个页面的<router-view>都规定好了,VUE只管按着matched渲染就好了。
深奥啊深奥,我是觉得这个代码写的非常复杂!!理解本质的唯一办法就是回到源码。
完整的调试代码
创建test-925.html文件,下面是完整的<body>代码。
<div id="app">
<router-view></router-view>
</div>
<template id="test">
<div>
<h2>测试页面</h2>
<router-view></router-view>
</div>
</template>
<script>
const routes = [
{
path: '/test-925.html',
redirect: '/test/a'
},
{
path: '/test',
component: {
template: '#test'
},
children: [
{
path: 'a',
component: {
template: '<h2 style="color:red">我是/test/a对应的组件内容!!!</h2>'
}
}
]
}
]
const router = new VueRouter({
routes,
mode: 'history',
base: '/test-rsa/cmd/vue/router/'
})
new Vue({
router
}).$mount('#app')
</script>
总结
这篇解释了路由嵌套,它在开发中非常常见,从源码而不是书本上去解读它。
猜你喜欢
- 2025-10-19 MySQL 8.2 支持读写分离!_mysql读写分离amoeba
- 2025-10-19 思科交换机,路由器如何关闭telnet 开启ssh服务
- 2025-10-19 FileZilla搭建FTP服务器图解教程_ftp怎么搭建
- 2025-10-19 深入VRRP 1 Vitual Router Redundancy Protocol
- 2025-10-19 精通Vue(10):vue-router(3)监控$route
- 2025-10-19 安装宽带时,ONU工作模式:桥接模式和路由器模式有啥区别?
- 2025-10-19 光猫的路由模式和桥接模式有啥区别?哪个更快?
- 2024-08-11 Vue实战051:各种懒加载技术实现(vue懒加载实现原理)
- 2024-08-11 手写vue路由(vue路由使用步骤)
- 2024-08-11 H3C路由器在企业网络中的常用操作
- 最近发表
-
- 用Cursor开启JAVA+AI生涯_javascirpt怎么开启
- 大数据调度服务监控平台_大数据调度是什么意思
- SpringBoot、MyBatis、Vue搭建一个Java企业应用开源框架源码分享
- 大数据技术之Flume_大数据volume的含义
- Jenkins运维之路(Slave容器节点)_jenkins slave工作原理
- 程序员自救指南:IDEA 卡成狗?我的 9G 堆内存调参表让你起飞 附避坑
- JMeter:一个简单的测试计划怎么做?
- Windows 命令行终端 PowerShell 美化计划
- JDK25即将发布!新特性概览_jdk52.0
- JDK 25 新特性极简总结(2025 年 9 月 16 日发布,LTS 长期支持)
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (77)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)