ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

vue-router 嵌套路由(Nested Routes)完全指南:从 URL 层级结构到组件嵌套渲染

vue-router 嵌套路由(Nested Routes)完全指南:从 URL 层级结构到组件嵌套渲染 前端路由【免费下载链接】vue-router The official router for Vue 2项目地址https://gitcode.com/gh_mirrors/vu/vue-router点击查看免费下载嵌套路由是 vue-routerVue 2 官方路由库中表达URL 分段与组件层级一一对应的核心能力一个 URL 的每一段路径对应一层组件外层组件内嵌router-view作为内层出口通过路由配置中的children数组逐层匹配。读完本文你将掌握嵌套路由的完整配置语法、绝对/相对子路径的取舍、空子路径默认页的实现以及其背后的源码级匹配原理并能直接在真实项目中落地多层嵌套的页面结构。为什么需要嵌套路由URL 结构与组件树的对应关系实际应用界面通常由多层嵌套的组件组合而成而 URL 中各段动态路径也天然对应这种嵌套结构。以用户模块为例/user/foo/profile /user/foo/posts ------------------ ----------------- | User | | User | | -------------- | | ------------- | | | Profile | | ------------ | | Posts | | | | | | | | | | | -------------- | | ------------- | ------------------ -----------------/user/foo/profile与/user/foo/posts共享/user/foo这一段——对应着User组件展示foo用户信息而profile/posts两段则分别对应User组件内部的个人资料与帖子两个子页面。借助 vue-router 的嵌套路由配置可以非常简单、声明式地表达这种关系。这一概念贯穿于本项目文档体系的各个语言版本本文对应的中文原文位于 docs/zh/guide/essentials/nested-routes.md英文版见 docs/guide/essentials/nested-routes.md。第一步在父组件模板中放置嵌套出口router-view先从上一节动态路由匹配创建的 app 出发。顶层出口位于根模板中div idapp router-view/router-view /divconst User { template: divUser {{ $route.params.id }}/div } const router new VueRouter({ routes: [{ path: /user/:id, component: User }] })这里的router-view是最顶层的出口top-level outlet渲染最高级路由匹配到的组件。关键点在于一个被渲染出来的组件同样可以包含自己的嵌套router-view。在User组件模板中再添加一个router-view就声明了我下面还有子页面出口const User { template: div classuser h2User {{ $route.params.id }}/h2 router-view/router-view /div }从源码看router-view是 src/components/view.js 中注册的RouterView函数式组件。它的渲染逻辑核心是通过向上遍历父链计算视图深度depth再按深度从route.matched[depth]取出对应层级的记录来渲染// src/components/view.js let depth 0 while (parent parent._routerRoot ! parent) { const vnodeData parent.$vnode ? parent.$vnode.data : {} if (vnodeData.routerView) { depth // 每遇到一层 router-view深度 1 } ... } const matched route.matched[depth] const component matched matched.components[name] if (!matched || !component) { return h() // 没有匹配时渲染空节点 }也就是说route.matched这个数组的下标天然对应嵌套层级第 0 层是根路由组件渲染在最外层router-view第 1 层是它的直接子路由组件渲染在父组件内的router-view依此类推。多层嵌套时router-view一层套一层深度自然递增。第二步用children配置声明嵌套路由要在嵌套出口中渲染组件需要在VueRouter构造配置中使用children选项const router new VueRouter({ routes: [ { path: /user/:id, component: User, children: [ { // 当 /user/:id/profile 匹配成功 // UserProfile 会被渲染在 User 的 router-view 中 path: profile, component: UserProfile }, { // 当 /user/:id/posts 匹配成功 // UserPosts 会被渲染在 User 的 router-view 中 path: posts, component: UserPosts } ] } ] })几个要点子路径不写前导/path: profile会被自动拼接到父路径/user/:id之后形成/user/:id/profile。父路由动态参数自动透传子路由的组件同样可以通过$route.params.id拿到:id的值因为:id位于 URL 更靠前的分段属于同一匹配链。children就是又一个routes数组每个子项同样是完整的路由配置对象可以继续带自己的children因此你可以无限层地嵌套视图。在 types/router.d.ts 中可以看到children?: RouteConfig[]就定义在路由配置基类_RouteConfigBase上与path、name、redirect、alias、meta、beforeEnter等并列说明嵌套是每条路由的通用能力interface _RouteConfigBase { path: string name?: string children?: RouteConfig[] redirect?: RedirectOption alias?: string | string[] meta?: RouteMeta beforeEnter?: NavigationGuard caseSensitive?: boolean pathToRegexpOptions?: PathToRegexpOptions }源码视角子路径是如何拼接与匹配的嵌套的拼接逻辑在 src/create-route-map.js 的addRouteRecord中遇到带children的路由时会先为父路由创建RouteRecord然后递归地把每个子路由作为新的addRouteRecord调用并把父记录作为parent传入// src/create-route-map.js if (route.children) { route.children.forEach(child { const childMatchAs matchAs ? cleanPath(${matchAs}/${child.path}) : undefined addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs) }) }真正的路径归一化在normalizePath中完成function normalizePath (path, parent, strict) { if (!strict) path path.replace(/\/$/, ) // 去掉末尾斜杠 if (path[0] /) return path // 以 / 开头 绝对路径直接返回 if (parent null) return path // 没有父路由 顶层路径 return cleanPath(${parent.path}/${path}) // 否则拼接父路径与子路径 }这段代码正是以/开头的嵌套路径会被当作根路径这一规则的实现拼接只发生在子路径不以斜杠开头时。cleanPath负责把可能出现的连续斜杠如父路径以/结尾时合并为单个斜杠见 src/util/path.js。匹配时src/create-matcher.js 中的match会遍历pathList中所有已归一化的路径用path-to-regexp编译出的正则逐一测试当前 URL命中后通过 src/util/route.js 的formatMatch沿着record.parent向上回溯把根记录 → 父记录 → 子记录的整条链按顺序放进route.matchedfunction formatMatch (record) { const res [] while (record) { res.unshift(record) // 头插法保证父在前、子在后的层级顺序 record record.parent } return res }于是route.matched的长度就等于嵌套深度router-view按深度索引逐层渲染两者形成精确对应——这正是嵌套路由能工作的闭环。绝对路径子路由以/开头即视为根路径要注意以/开头的嵌套路径会被当作根路径。这让你可以充分使用组件嵌套而无须设置嵌套的 URL。例如把上面的posts子路由写成children: [ { path: /posts, component: UserPosts } ]那么访问/posts时UserPosts会被渲染在User组件的router-view中——虽然 URL 里根本没有/user/:id这一段但组件树依然是Root → User → UserPosts。这为复用组件布局、却不想被 URL 结构绑架的场景提供了很大灵活性。这一点在仓库的嵌套路由示例 examples/nested-routes/app.js 中有完整演示。示例中Parent组件的子路由同时包含了相对路径与绝对路径两种写法const router new VueRouter({ mode: history, base: __dirname, routes: [ { path: /, redirect: /parent }, { path: /parent, component: Parent, children: [ // 相对路径渲染在 /parent 上 { path: , component: Default }, // 相对路径渲染在 /parent/foo 上 { path: foo, component: Foo }, // 相对路径渲染在 /parent/bar 上 { path: bar, component: Bar }, // 注意这是绝对路径 // 利用组件嵌套而不受嵌套 URL 限制 // 访问 /baz 时组件链为 Root - Parent - Baz { path: /baz, component: Baz }, // 继续嵌套形成三层结构 { path: qux/:quxId, component: Qux, children: [ { path: quux, name: quux, component: Quux }, { path: quuy, name: quuy, component: Quuy } ] }, { path: quy/:quyId, component: Quy }, { name: zap, path: zap/:zapId?, component: Zap } ] } ] })对应的端到端测试 test/e2e/specs/nested-routes.js 验证了绝对路径子路由的行为——点击第 4 个链接/baz后 URL 变为/baz但.view中同时包含Parent与baz的文本.click(li:nth-child(4) a) .assert.urlEquals(http://localhost:8080/nested-routes/baz) .assert.containsText(.view, Parent) .assert.containsText(.view, baz)这说明URL 是绝对路径、组件树依然是嵌套的这一特性同时被源码与测试双重确认。示例中还有qux/:quxId下再挂quux/quuy的三层嵌套以及可选参数zap/:zapId?的用法可以作为直接复制运行的完整参考。空路径子路由让/user/:id本身也有内容配置了子路由之后当访问/user/foo时父路径匹配成功、但没有匹配到任何子路径User的出口不会渲染任何东西因为route.matched[depth]对应的子记录不存在router-view直接渲染空节点对应 src/components/view.js 中if (!matched || !component) return h()的分支。如果你希望/user/:id本身也渲染点内容可以提供一个空的子路由路径const router new VueRouter({ routes: [ { path: /user/:id, component: User, children: [ // 当 /user/:id 匹配成功 // UserHome 会被渲染在 User 的 router-view 中 { path: , component: UserHome } // ...其他子路由 ] } ] })访问/user/foo时UserHome就会出现在User内部的router-view中URL 上没有任何额外的分段。与命名路由搭配时的注意事项如果父路由同时带有name又存在空路径子路由vue-router 在开发模式下会给出一条警告见 src/create-route-map.jsif ( route.name !route.redirect route.children.some(child /^\/?$/.test(child.path)) ) { warn(false, Named Route ${route.name} has a default child route. When navigating to this named route (:to{name: ${route.name}}), the default child route will not be rendered. ... ) }原因是当使用:to{ name: parent }这样的命名导航时路由匹配到的记录只有父记录本身route.matched里并不包含默认子路由因此默认子组件不会被渲染对应 GH Issue #629。官方建议去掉父路由的name改用默认子路由的name来命名链接以确保空路径子路由能被正确渲染。实战组装一个完整的多层嵌套页面把上述知识组合起来一个典型的三层嵌套应用结构如下const router new VueRouter({ routes: [ { path: /user/:id, component: User, // 外层用户信息骨架导航栏、侧边栏等 children: [ { path: , // 默认子路由/user/:id component: UserHome }, { path: profile, // /user/:id/profile component: UserProfile }, { path: posts, // /user/:id/posts component: UserPosts }, { path: settings, // 三层嵌套/user/:id/settings/security component: UserSettings, children: [ { path: security, component: SecuritySettings }, { path: notifications, component: NotificationSettings } ] } ] } ] })组件侧只需让每层有子页面的组件都放一个router-view层与层之间就能无缝衔接// User 组件负责 /user/:id 外层骨架 const User { template: div classuser h2User {{ $route.params.id }}/h2 router-view/router-view /div } // UserSettings 组件负责三层嵌套的中间层 const UserSettings { template: div classsettings h3设置/h3 router-view/router-view /div }配合router-link即可在任意层级导航例如:to{ name: settings-security }为深层路由命名后按名跳转或直接写路径/user/foo/posts。小结与进一步阅读嵌套路由的本质可以概括为三句话声明式嵌套路由配置中父路由的children数组与组件模板中嵌套的router-view一一对应路径拼接规则不以/开头的子路径自动拼接在父路径之后以/开头的子路径视为根路径但组件嵌套关系保持不变空路径即默认页path: 的子路由让父路径本身也有渲染内容是默认子页面的标准写法。想要更深入可以继续阅读仓库内的相关文档与源码中文文档全文docs/zh/guide/essentials/nested-routes.md英文原文docs/guide/essentials/nested-routes.md可运行示例含绝对路径、三层嵌套、可选参数examples/nested-routes/app.js端到端测试逐条验证各 URL 与渲染结果test/e2e/specs/nested-routes.js路由表构建与子路径归一化源码src/create-route-map.js嵌套出口渲染与深度计算源码src/components/view.js匹配器与route.matched组装src/create-matcher.js 与 src/util/route.js路由配置类型定义children字段types/router.d.ts掌握嵌套路由后你可以继续学习动态路由匹配、命名路由、命名视图同一层级渲染多个router-view以及嵌套路由中的导航守卫从而完整驾驭 vue-router 的页面组织能力。赞分享前端路由【免费下载链接】vue-router The official router for Vue 2项目地址https://gitcode.com/gh_mirrors/vu/vue-router点击查看免费下载相关推荐Vue Router 嵌套路由Nested Routes完全指南children 配置、绝对路径与 router-view 渲染层级Vue Router 嵌套路由Nested Routes完全指南children 配置、绝对路径与 router view 渲染层级 嵌套路由是 vue前端路由Tech Interview Handbook终极部署指南Vercel生产环境配置全攻略Tech Interview Handbook终极部署指南Vercel生产环境配置全攻略 Tech Interview Handbook是一个为忙碌软件工程师前端路由iir1性能优化技巧10个提升实时DSP处理效率的方法iir1性能优化技巧10个提升实时DSP处理效率的方法 iir1是一个用C编写的实时IIR滤波器库专为数字信号处理 DSP 设计。它提供了Butterw前端路由上一篇反检测爬虫新范式Crawl4AI用户代理生成器完全指南下一篇Cloud189Checkin天翼网盘自动签到完全指南免费白嫖随机容量的入门第一课创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表