虽然利用动态组件可以实现组件切换,但是用户刷新网页或者通过URL地址重新访问网页时,组件的切换状态无法保留。为了解决这个问题,可以使用路由实现组件切换。

后端路由和前端路由

后端路由

比如Node.js环境中的Express框架,服务器收到请求后会通过路由寻找当前请求的URL地址对应的处理程序。

前端路由

前端路由的整个过程发生在浏览器端,当URL地址改变时不需要向服务器发起一个加载页面的请求,而是维持当前页面的情况下切换页面中的显示内容。

  1. Hash模式:http://www.example.com/#/user
    通过URL中从#开始的部分来切换不同的页面内容。
  2. HTML5模式:http://www.example.com/user
    利用HTML5的history.pushState方法来改变URL地址,但是需要服务器端支持。

基本使用

  1. 定义路由组件

  2. 定义路由链接和路由视图

    • router-link:导航链接 <router-link to="/user">用户</router-link>
    • router-view:路由视图 <router-view></router-view>
  3. 创建路由模块
    如果使用Hash模式则导入createWebHashHistory,如果使用HTML5模式则导入createWebHistory

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import{ createRouter, createWebHashHistory } from 'vue-router'
    import Home from './views/Home.vue'
    import About from './views/About.vue'

    const router = createRouter({
    history: createWebHashHistory(),
    routes:[
    { path: '/home', component: Home },
    { path: '/about', component: About }
    ]
    }
    )

    如果希望懒加载的话可以使用import函数,比如:

    1
    2
    3
    4
    5
    routes:[
    { path: '/home' , component: () => import('./views/Home.vue') }
    { path:'/about' , component: ()=> import('./views/About.vue') }
    ]

  4. 导入并挂载路由模块

    1
    2
    3
    4
    5
    6
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router.js'
    const app = createApp(App)
    app.use(router)
    app.mount('#app')

路由重定向

当用户在访问一个URL地址时强制跳转到另一个URL地址,从而展示特定的组件

1
{ path: '/' , redirect: '/home' }

嵌套路由

使用children属性定义子路由匹配规则

1
2
3
4
5
6
7
8
9
10
routes:[
{
path: '/home',
component: Home,
children:[
{ path: 'path1', component: Component1},
{ path: 'path2', component: Component2}
]
}
]

在组件中定义子路由连接

1
2
<router-link to="/home/path1">path1</router-link>
<router-link to="/home/path2">path2</router-link>

动态路由

组件的内容会根据URL地址的变化而变化

1
{ path: '/user/:id', component: User }
  • 在组件中监听动态路由的变化

    1
    2
    3
    4
    const route = useRoute()
    watch(() => route.path, (path) => {
    console.log(path)
    })
  • 获取动态路径参数值

    1
    2
    const route = useRoute()
    console.log($route.params.id)
  • 使用props获取路由参数值

    1
    2
    3
    const props = defineProps({
    id: String
    })

    在router.js中也要开启props穿参

    1
    { path:':id', component: User, props: true }

命名路由

使用name属性定义路由名称

1
{ path: '/home:id', component: Home, name: 'home' }
1
<route-link :to="{ name: 'home' , params:{ id: 1 } }">Home</route-link>

编程式导航

  • push:添加一个新的历史记录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const router = useRouter()
    // 字符串路径
    router.push('/home')
    // 带有路径的对象
    router.push({ path: '/home' })
    // 命名路由
    router.push({ name: 'home', params: { id: 1 } })
    // 带查询参数
    router.push({ path: '/home', query: { id: 1 } })
    // 带Hash值
    router.push({ path: '/home', hash: '#top' })
  • replace:替换当前历史记录

    1
    router.replace('/home')
  • go:前进或后退

    1
    2
    router.go(1) // 前进
    router.go(-1) // 后退

导航守卫

用来控制路由的访问权限

  • 全局导航守卫
    • router.beforeEach((to, from, next) => {}) 全局前置守卫
      • to是要进入的路由,from是要离开的路由,next是一个函数,如果不接受next,则默认允许用户访问每一个路由,如果接受了next,则必须调用next方法才能继续访问路由
    • router.afterEach((to, from) => {}) 全局后置守卫
  • 导航独享守卫
    • 在路由配置中定义beforeEnter属性
  • 组件导航守卫
    • beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave