-
2.7 命名视图
-
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。
<router-view class="view left-sidebar" name="LeftSidebar"></router-view> <router-view class="view main-content"></router-view> <router-view class="view right-sidebar" name="RightSidebar"></router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):
const router = createRouter({ history: createWebHashHistory(), routes: [ { path: '/', components: { default: Home, // LeftSidebar: LeftSidebar 的缩写 LeftSidebar, // 它们与 `<router-view>` 上的 `name` 属性匹配 RightSidebar, }, }, ], })
例子:
main.js
import { createApp } from 'vue' import App from './App.vue' import { router } from './router' const app = createApp(App).use(router) app.mount('#app')
router.jsimport { createRouter, createWebHistory } from 'vue-router' import First from './views/First.vue' import Second from './views/Second.vue' import Third from './views/Third.vue' export const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', // a single route can define multiple named components // which will be rendered into <router-view>s with corresponding names. components: { default: First, a: Second, b: Third, }, }, { path: '/other', components: { default: Third, a: Second, b: First, }, }, ], })
First.vue<template> <h1>First Seciton</h1> </template>
Second.vue
<template> <h1>Second section</h1> </template>
Third.vue<template> <h1>Third section</h1> </template>
App.vue<template> <h1>Named Views</h1> <ul> <li> <router-link to="/">First page</router-link> </li> <li> <router-link to="/other">Second page</router-link> </li> </ul> <router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view> </template> <script> export default { name: "App", }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #2c3e50; } .router-link-active { color: orange; } .router-link-exact-active { color: crimson; } </style> <style scoped> ul { display: flex; list-style: none; padding: 0; margin: 0; } li:not(:last-of-type) { margin-right: 1rem; } </style>
嵌套命名视图
我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件。我们以一个设置面板为例:
/settings/emails /settings/profile +-----------------------------------+ +------------------------------+ | UserSettings | | UserSettings | | +-----+-------------------------+ | | +-----+--------------------+ | | | Nav | UserEmailsSubscriptions | | +------------> | | Nav | UserProfile | | | | +-------------------------+ | | | +--------------------+ | | | | | | | | | UserProfilePreview | | | +-----+-------------------------+ | | +-----+--------------------+ | +-----------------------------------+ +------------------------------+
1.Nav 只是一个常规组件。
2.UserSettings 是一个视图组件。
3.UserEmailsSubscriptions、UserProfile、UserProfilePreview 是嵌套的视图组件。
注意:我们先忘记 HTML/CSS 具体的布局的样子,只专注在用到的组件上。
UserSettings 组件的 <template> 部分应该是类似下面的这段代码:
<!-- UserSettings.vue --> <div> <h1>User Settings</h1> <NavBar /> <router-view /> <router-view name="helper" /> </div>
那么你就可以通过这个路由配置来实现上面的布局:
{ path: '/settings', // 你也可以在顶级路由就配置命名视图 component: UserSettings, children: [{ path: 'emails', component: UserEmailsSubscriptions }, { path: 'profile', components: { default: UserProfile, helper: UserProfilePreview } }] }
完整例子:
main.js
import { createApp } from 'vue' import App from './App.vue' import { router } from './router' const app = createApp(App).use(router) app.mount('#app')
App.vue<template> <h1>Nested Named Views</h1> <router-view></router-view> </template> <script> export default { name: "App", }; </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #2c3e50; } .router-link-active { color: orange; } .router-link-exact-active { color: crimson; } .us { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto; grid-template-areas: "header header" "nav content" "nav helper"; } h2 { grid-area: header; } .us__nav { grid-area: nav; border: 1px dotted; margin-right: 0.75rem; padding: 0.3rem; } .us__content { grid-area: content; } .us__content--helper { grid-area: helper; } </style> <style scoped> ul { display: flex; list-style: none; padding: 0; margin: 0; } li:not(:last-of-type) { margin-right: 1rem; } </style>
router.jsimport { createRouter, createWebHistory } from 'vue-router' import UserSettings from './views/UserSettings.vue' import UserEmailsSubscriptions from './views/UserEmailsSubscriptions.vue' import UserProfile from './views/UserProfile.vue' import UserProfilePreview from './views/UserProfilePreview.vue' export const router = createRouter({ history: createWebHistory(), routes: [ { path: '/settings', // You could also have named views at tho top component: UserSettings, children: [ { path: 'emails', component: UserEmailsSubscriptions, }, { path: 'profile', components: { default: UserProfile, helper: UserProfilePreview, }, }, ], }, ], })
UserSettingsNav.vue<template> <div class="us__nav"> <router-link to="/settings/emails">emails</router-link> <br /> <router-link to="/settings/profile">profile</router-link> </div> </template>
UserSettings.vue<template> <div class="us"> <h2>User Settings</h2> <UserSettingsNav /> <router-view class="us__content" /> <router-view name="helper" class="us__content us__content--helper" /> </div> </template> <script> import UserSettingsNav from "./UserSettingsNav.vue"; export default { components: { UserSettingsNav }, }; </script>
UserProfilePreview.vue<template> <div> <h3>Preview of your profile</h3> </div> </template>
UserProfile.vue<template> <div> <h3>Edit your profile</h3> </div> </template>
UserEmailsSubscriptions.vue<template> <div> <h3>Email Subscriptions</h3> </div> </template>
Home.vue<template> <h1>Home</h1> </template>
About.vueAbout.vue
- 留下你的读书笔记
- 你还没登录,点击这里
-
用户笔记留言