Code前端首页关于Code前端联系我们

想搞懂vue-router里的RouterView,却被各种概念绕晕?别慌,这篇用问答形式把RouterView从基础到进阶的知识点掰碎了讲,新手也能轻松跟上~

terry 13小时前 阅读数 11 #Vue
文章标签 router RouterView

RouterView到底是做什么的?

RouterView是vue-router提供的容器」,当你在项目里配置好路由规则(比如访问/home时显示Home组件),RouterView就负责把匹配到的组件渲染到页面指定位置。

举个生活例子:你手机里的「微信」App,底部tab切换「聊天」「通讯录」「发现」时,顶部和底部导航栏不变,中间区域切换不同页面——这个中间可变的区域,就相当于RouterView的作用。

它还有个“好搭档”<RouterLink><RouterLink>负责生成可点击的导航(比如页面上的“首页”按钮),RouterView负责展示点击后对应的内容,两者配合完成「导航→渲染」的流程。

新手第一步:怎么在项目里用RouterView?

想用RouterView,得先把vue-router集成到项目里,步骤分3步:

安装并配置vue-router

如果是Vue3 + Vite项目,先装依赖:npm i vue-router,然后在src/router/index.js里配置路由规则:

import { createRouter, createWebHistory } from 'vue-router'
// 导入要渲染的页面组件
import Home from '../views/Home.vue' 
const routes = [
  { 
    path: '/', // 访问根路径时
    component: Home // 渲染Home组件
  }
]
const router = createRouter({
  history: createWebHistory(), // 路由模式(还有hash模式等)
  routes // 上面定义的路由规则数组
})
export default router

把路由实例注入Vue应用

main.js里,把router挂载到App上:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 导入上面配置的router
createApp(App)
  .use(router) // 注入路由
  .mount('#app')

在模板里放RouterView

打开App.vue(或其他需要渲染路由的组件),用<RouterView/>占个“坑”:

<template>
  <div class="app-wrapper">
    <!-- 导航区域,比如放RouterLink -->
    <nav>
      <RouterLink to="/">首页</RouterLink>
    </nav>
    <!-- 路由内容渲染区 -->
    <RouterView/> 
  </div>
</template>
<script setup>
import { RouterView, RouterLink } from 'vue-router' // 导入组件
</script>

这样一来,访问根路径时,Home组件就会自动渲染到<RouterView/>的位置,整个“导航→渲染”的流程就跑通啦~

遇到复杂页面?RouterView和嵌套路由咋配合?

很多项目有「布局嵌套」需求:比如后台管理系统,顶部有导航栏、左侧有侧边栏,只有中间内容区随路由变化,这时候就得用「嵌套路由」,而RouterView是嵌套路由的核心载体。

配置嵌套路由规则

在路由配置里,给父路由加children数组,代表子路由:

const routes = [
  {
    path: '/admin', // 父路由路径
    component: AdminLayout, // 父路由对应的布局组件(包含侧边栏、顶栏)
    children: [
      { 
        path: 'dashboard', // 子路由路径,完整路径是/admin/dashboard
        component: Dashboard // 子路由组件(中间内容区)
      },
      { 
        path: 'settings', 
        component: Settings 
      }
    ]
  }
]

父组件里放RouterView渲染子组件

打开AdminLayout.vue(父布局组件),在需要渲染子内容的位置放<RouterView/>

<template>
  <div class="admin-layout">
    <aside>左侧侧边栏(固定不变)</aside>
    <header>顶部导航(固定不变)</header>
    <main>
      <RouterView/> <!-- 这里渲染子路由的Dashboard或Settings -->
    </main>
  </div>
</template>

这样访问/admin/dashboard时,页面结构是:AdminLayout的侧边栏+顶栏 + RouterView渲染的Dashboard;切换到/admin/settings时,中间区域自动换成Settings——完美实现“布局不变,内容切换”~

RouterView能传参吗?怎么给组件递数据?

必须能!常见场景比如“用户详情页需要根据ID展示信息”,这时候得把路由里的参数传给渲染的组件,主要有两种方式:

方式1:用路由参数($route.params

先在路由规则里定义动态参数(用参数名):

const routes = [
  { 
    path: '/user/:id', // :id是动态参数,比如访问/user/123,id就是123
    component: User 
  }
]

然后在User组件里,通过$route.params.id获取参数:

<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id) // 输出路由里的id,比如123
</script>

方式2:用props解耦(更推荐)

如果想让组件不直接依赖$route(更灵活、易测试),可以开启props模式:

const routes = [
  { 
    path: '/user/:id', 
    component: User,
    props: true // 开启后,路由参数会自动传给User组件的props
  }
]

然后User组件用props接收:

<script setup>
const props = defineProps(['id']) // 接收id参数
console.log(props.id) // 同样能拿到123
</script>

方式3:在RouterView上直接传动态数据

如果想给所有匹配的路由组件传通用数据(比如全局配置),可以在<RouterView>上用v-bind传值:

<RouterView :theme="currentTheme" />

然后路由组件里用props接收theme即可,不过这种方式适合全局通用数据,要是不同路由需要不同数据,结合「路由元信息(meta)」更灵活~

切换路由时页面状态总丢失?RouterView怎么缓存?

比如表单页面,切出去再回来,输入的内容没了;或者列表页,滚动位置重置了——这时候得给RouterView加缓存,保留组件状态,Vue的<KeepAlive>组件就是干这个的~

基础用法:用KeepAlive包裹RouterView

在模板里,把<RouterView>包在<KeepAlive>里:

<template>
  <div>
    <KeepAlive>
      <RouterView/>
    </KeepAlive>
  </div>
</template>

这样一来,路由切换时,已渲染的组件实例会被缓存,组件的生命周期钩子(比如onMounted)不会重复执行、滚动位置这些状态就保留下来了~

进阶:控制哪些组件缓存(按需缓存)

如果不是所有页面都要缓存(比如登录页不需要),可以用<KeepAlive>include/exclude属性,或者结合「路由元信息(meta)」:

<template>
  <KeepAlive :include="keepAliveComponents">
    <RouterView/>
  </KeepAlive>
</template>
<script setup>
import { computed } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
// 根据当前路由的meta.keepAlive,动态决定是否缓存
const keepAliveComponents = computed(() => {
  return router.currentRoute.value.meta.keepAlive 
    ? [router.currentRoute.value.name] 
    : []
})
</script>

然后在路由配置里标记哪些页面要缓存:

const routes = [
  {
    path: '/profile',
    component: Profile,
    name: 'Profile', // 要和上面的name对应
    meta: { keepAlive: true } // 标记需要缓存
  },
  {
    path: '/login',
    component: Login,
    meta: { keepAlive: false } // 不需要缓存
  }
]

这样只有标记了keepAlive: true的组件会被缓存,灵活性拉满~

页面没匹配到路由?RouterView的fallback咋用?

当用户访问了不存在的路径(比如/xxx),RouterView默认啥都不渲染,但我们可以用fallback属性给个“兜底”提示,比如404页面:

方式1:用fallback属性

<RouterView fallback="抱歉,页面走丢了~"/>

这样没匹配到路由时,会显示“抱歉,页面走丢了~”。

方式2:用插槽自定义内容

如果想搞复杂点的兜底(比如加个404组件、按钮),用插槽更灵活:

<RouterView>
  <template #fallback>
    <div class="error-page">
      <h1>404 - 页面不存在</h1>
      <RouterLink to="/">返回首页</RouterLink>
    </div>
  </template>
</RouterView>

路由配置里要记得加「通配符路由」()放在最后,确保能匹配到所有无效路径:

const routes = [
  // 其他路由...
  { 
    path: '/:pathMatch(.*)*', // 匹配所有未定义的路径
    component: Error404 
  }
]

这样结合fallback和通配符路由,用户访问错误路径时体验更友好~

一个页面要渲染多个区域?RouterView的命名视图是啥?

比如做博客详情页,需要同时渲染「文章内容」「评论区」「相关推荐」三个独立组件,这时候命名视图就能派上用场——给RouterView起不同名字,对应渲染不同组件。

配置命名视图的路由规则

路由规则里用components(注意是复数),给每个组件分配名字:

const routes = [
  {
    path: '/blog/:id',
    components: {
      default: Article, // 对应没有name的RouterView
      comments: Comments, // 对应name="comments"的RouterView
      related: RelatedPosts // 对应name="related"的RouterView
    }
  }
]

模板里用命名RouterView

在页面模板里,给RouterView加name属性,对应路由里的键:

<template>
  <div class="blog-detail">
    <!-- 渲染Article组件(default对应的RouterView) -->
    <RouterView/> 
    <!-- 渲染Comments组件 -->
    <RouterView name="comments"/>
    <!-- 渲染RelatedPosts组件 -->
    <RouterView name="related"/>
  </div>
</template>

这样访问/blog/123时,三个区域会同时渲染对应的组件,实现“多区域并行渲染”的效果~

性能优化:RouterView和异步组件、动态路由咋结合?

项目大了,首屏加载慢?用「异步组件(懒加载)」让RouterView只在需要时加载组件代码;业务复杂,需要动态切换组件?用「动态路由」让RouterView根据条件渲染不同组件。

异步组件(懒加载)

路由配置里,把component改成函数形式,访问时才加载组件代码:

const routes = [
  {
    path: '/about',
    component: () => import('../views/About.vue') // 访问/about时才加载About.vue
  }
]

RouterView会正常渲染异步加载的组件,加载过程中可以加个loading状态提示(比如在App.vue里监听路由加载状态)。

动态路由(根据条件切换组件)

比如根据用户角色,显示不同的后台首页:

const routes = [
  {
    path: '/dashboard',
    component: () => {
      const role = localStorage.getItem('role') // 假设从本地存贮取角色
      return role === 'admin' 
        ? import('../views/AdminDashboard.vue') 
        : import('../views/UserDashboard.vue')
    }
  }
]

这样RouterView会根据用户角色,动态渲染AdminDashboard或UserDashboard——一套路由,适配多场景~

看完这些,是不是觉得RouterView没那么难了?总结下:它是路由内容的“展示容器”,能配合嵌套路由、传参、缓存、命名视图等玩法,帮我们搞定单页应用的各种复杂场景,多动手写demo,结合项目需求去试,很快就能掌握啦~如果还有疑问,评论区随时喊我~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门