目录

路由简介

路由入门案例

编程式路由(useRouter)

路由传参(useRoute)

路由守卫

案例测试

完!


路由简介

什么是路由:

        定义:路由就是根据不同的 URL 地址展示不同的内容或页面

作用:

        SPA 中,可以实现不同视图之间的无刷新切换

        实现页面认证和权限控制

路由入门案例

案例需求:

创建项目和导入路由依赖:

npm create vite@4 

npm install

npm install vue-router@4 --save

准备页面组件

单独在 src 文件夹下面创建一个 routers 文件夹,里面存放 router.js

// 导入创建路由对象需要的函数
import {createRouter,createWebHashHistory} from 'vue-router'

// 导入 .vue 组件
import Home from '../comments/Home.vue'
import List from '../comments/List.vue'
import Add from '../comments/Add.vue'
import Update from '../comments/Update.vue'

// 创建一个路由对象
const router = createRouter({
    // history 属性用于记录路由的历史
    history:createWebHashHistory(),
    // routes 用于定义多个不同的路径和组件之间的对应关系
    routes:[
        {
            path:'/home',
            component:Home
        },
        {
            path:'/list',
            component:List
        },
        {
            path:'/add',
            component:Add
        },
        {
            path:'/update',
            component:Update
        },
        {
            path:'/',
            component:Home
        }
    ]
})

// 向外暴露
export default rouer

配置 main.js 文件:

import { createApp } from 'vue'

import App from './App.vue'
// 在整个 App.vue 中可以使用路由
import router from './routers/router.js'

const app = createApp(App)
// 绑定路由对象
app.use(router)
// 挂载视图
app.mount('#app')

App.vue 的页面

<script setup>
</script>

<template>
  <div>
    App 开头的内容 <br>
    <router-link to = "/Home">Home页</router-link><br>
    <router-link to = "/List">List页</router-link><br>
    <router-link to = "/Add">Add页</router-link><br>
    <router-link to = "/Update">Update页</router-link><br>
    <hr>

    <!-- router-view 标签会背替换成具体的 .vue -->
    <router-view></router-view>
    <hr>
    App 结束的内容
  </div>
</template>

<style scoped>

</style>

这样,就基础的实现了我们的需求:

我们还可以在不同的页面中进行相互跳转:

例如,在 Home 页中同样加一个 router-link 标签,实现从 Home 页向 Add 页的跳转:

<script setup>
</script>

<template>
  <div>
    <router-link to="/add">Add页</router-link>
    <h1> Home 页面</h1>
  </div>
</template>

<style scoped>

</style>

也可以实现重定向,比如当我们的路径为 /showAll 的时候,重定向到 /list:

先在 router.js 中的 router 对象中,配置 path 和对应的 redirect

然后在 App.vue 中添加 router-link 的标签即可

编程式路由(useRouter)

声明式路由:

<router-link to = "/list">list页</router-link> 这种路由,点击后只能切换 /list 对应的组件,是固定的

编程式路由:

通过 useRouter,动态决定向那个组件切换的路由

这里的 useRouter 方法返回的是一个 router 对象,可以用它来做,如导航到新页面,返回上一面等操作

<script setup>
  import {useRouter} from 'vue-router'
  import {ref} from 'vue'
  let myPath = ref('')
  const router = useRouter()

  function showList() {
    // 编程式路由实现页面跳转
    // 方式一:router.push("/list")
    router.push({path:"/list"})
  }

  function goMyPage() {
    router.push(myPath.value)
  }
</script>

<template>
  <div>

    <!-- 声明式路由 -->
    <router-link to="/home">home</router-link><br>
    <router-link to="/list">list</router-link><br>
    <router-link to="/add">add</router-link><br>
    <router-link to="/update">update</router-link><br>


    <!-- 编程式路由 -->
    <button @click="showList()">list</button><br>

    <button @click="goMyPage()">Go</button><input type = "text" v-model="myPath">
    <router-view></router-view>
  </div>
</template>

<style scoped>

</style>

路由传参(useRoute)

路径参数:

        在路径中使用一个动态字段来实现,我们称之为路径参数。

        例如:查看数据详情 /showDetail/1, 1 就是要查看详情的 id,可以动态填值。

键值对参数:

        类似与 get 请求通过 URL 传参,数据是键值对形式的。

        例如:查看数据详情 /showDetail?hid=1,hid 就是要传递的键值对参数。

读取参数:

在 Vue3 和 Vue Router4 中,我们可以使用 useRoute 这个函数,从 Vue 的组合式 API 中获取路由对象。

useRoute 方法返回的是当前的 route 对象,我们可以用它来获取关于当前路由的信息,如当前的路径,键值对参数等。


案例需求:切换到 ShowDetail.vue 组件时,向该组件通过路由传递参数


1.路径参数:{声明式路由和编程式路由}

准备一个 ShowDetail.vue 页面:

<script setup>

</script>

<template>
    <div>
        <h1>ShowDetail接收路径参数</h1>
    </div>
</template>

<style scoped>

</style>

在 router.js 中进行配置:

// 导入创建路由的相关方法
import { createRouter, createWebHashHistory } from "vue-router";

// 导入 .vue 组件
import Home from '../components/Home.vue'
import Add from '../components/Add.vue'
import List from '../components/List.vue'
import Update from '../components/Update.vue'
import ShowDetail from '../components/ShowDetail.vue'

const router = createRouter({
    history:createWebHashHistory(),
    routes:[

        {
            path:"/showDetail/:id/:language",
            component:ShowDetail
        },
        {
            path:"/",
            component:Home,
        },
        {
            path:"/home",
            component:Home,
        },
        {
            path:"/list",
            component:List,
        },
        {
            path:"/add",
            component:Add,
        },
        {
            path:"/update",
            component:Update
        }
    ]
})
export default router

ShowDetail.vue:

<script setup>
/**
 * 接收传递过来的路径参数
 * useRoute 函数是用来接收参数的
 */
    import {useRoute} from 'vue-router'
    import {ref,onUpdated} from 'vue'
    
    let languageId = ref(0)
    let languageName = ref("")

    let route = useRoute()
    languageId.value=route.params.id
    languageName.value=route.params.language

    // 让页面可以实时更新~
    onUpdated(()=>{
        languageId.value=route.params.id
        languageName.value=route.params.language
    })
</script>

<template>
    <div>
        <h1>ShowDetail接收路径参数</h1>
        <h3>{{languageId}}{{languageName}}是世界上最好的语言</h3>
    </div>
</template>

<style scoped>

</style>

App.vue:

<script setup>
  import {useRouter} from 'vue-router'
  import {ref} from 'vue'
  const router = useRouter()

  function showDetail(id,language){
    router.push(`/showDetail/${id}/${language}`)
  }
</script>

<template>
  <div>
    <router-link  to="/showDetail/1/java">声明式路由路径传参</router-link>

    <button @click="showDetail(2,'PHP')">编程式路由路径传参</button>
    <hr>


    <router-view></router-view>
  </div>
</template>

<style scoped>

</style>

2. 键值对参数{声明式路由和编程式路由}

router.js:

// 导入创建路由的相关方法
import { createRouter, createWebHashHistory } from "vue-router";

// 导入 .vue 组件
import Home from '../components/Home.vue'
import Add from '../components/Add.vue'
import List from '../components/List.vue'
import Update from '../components/Update.vue'
import ShowDetail from '../components/ShowDetail.vue'
import ShowDetail2 from '../components/showDetail2.vue'
const router = createRouter({
    history:createWebHashHistory(),
    routes:[
        {
            path:"/showDetail2",
            component:ShowDetail2
        },
        {
            path:"/showDetail/:id/:language",
            component:ShowDetail
        },
        {
            path:"/",
            component:Home,
        },
        {
            path:"/home",
            component:Home,
        },
        {
            path:"/list",
            component:List,
        },
        {
            path:"/add",
            component:Add,
        },
        {
            path:"/update",
            component:Update
        }
    ]
})
export default router

ShowDetail2:

<script setup>
/**
 * 接收传递过来的路径参数
 * useRoute 函数是用来接收参数的
 */
    import {useRoute} from 'vue-router'
    import {ref,onUpdated} from 'vue'
    
    let languageId = ref(0)
    let languageName = ref("")

    let route = useRoute()
    languageId.value=route.query.id
    languageName.value=route.query.language

    onUpdated(()=>{
        languageId.value=route.query.id
        languageName.value=route.query.language
    })
</script>

<template>
    <div>
        <h1>ShowDetail2接收键值对参数</h1>
        <h3>{{languageId}}{{languageName}}是世界上最好的语言</h3>
    </div>
</template>

<style scoped>

</style>

App.vue:

<script setup>
  import {useRouter} from 'vue-router'
  import {ref} from 'vue'
  const router = useRouter()

  function showDetail(id,language){
    router.push(`/showDetail/${id}/${language}`)
  
  }

  function showDetail2(id,language){
    router.push(`/showDetail2?id=${id}&language=${language}`)

  }
</script>

<template>
  <div>
    
    <router-link to ="/showDetail2?id=1&language=java">声明式路由键值对传参</router-link>
    <button @click="showDetail2(2,'PHP')">编程式路由键值对传参</button>
    <hr>


    <router-view></router-view>
  </div>
</template>

<style scoped>

</style>

路由守卫

在 Vue3 中,路由首位是用于在路由切换期间,进行一些特定任务的回调函数。路由守卫可以用于许多任务:例如验证用户是否已经登录,在路由切换前提供确认提示,请求数据等。

        全局前置守卫:在路由切换前被调用,可以用于验证用户是否已登录,中断导航,请求数据等。

        全局后置首位:在路由切换之后被调用,可以用于处理数据,操作 DOM,记录日志等

        守卫代码的位置:在 router.js 文件中

// 设置全局前置首位
// 每次路由切换页面前,都会执行 beforeEach 中的回调函数
router.beforeEach(
    (to,from,next)=>{
        /**
         * from 上一个页面 表示从哪里来
         * to 下一个页面 表示到哪里去
         * next 放行的方法,只有执行了该方法,才会放行路由 类似与过滤器中的 filterChain.doFilter
         * next() 放行
         * next("/路径") 路由的重定向,可以转发到其他地址
         * 但是到达目标组件前会在此经过前置路由守卫,需要注意判断,避免无限重定向
         * 
         * 
         */
        console.log("beforeEach")
        console.log(from.path)
        console.log(to.path)
        next()
    }
)
// 设置全局后置路由
// 每次路由切换页面后,都会执行 afterEach 中的回调函数
router.afterEach(
    ()=>{
        console.log("afterEach")
    }
)

案例测试

要求:登录案例,登录以后才可以进入 home 页面,否则必须进入 login 页面

Login.vue:

<script setup>
  import {ref} from 'vue'
  import {useRouter} from 'vue-router'

  let username = ref('')
  let password = ref('')
  let router = useRouter()

  let login = () => {
    console.log(username.value, password.value)
    if (username.value == 'root' && password.value == '123456') {
      router.push({path:'/home',query:{'username':username.value}})
      // 登录成功利用前端存储机制,存储账号
      localStorage.setItem('username', username.value)
    } else {
      alert("登陆失败,账号或密码错误")
    }
  }
</script>

<template>
  <div>
    账号:<input type = "text" v-model="username" placeholder="请输入账号"><br>
    密码:<input type = "password" v-model="password" placeholder="请输入密码"><br>
    <button @click="login()">登录</button>
  </div>
</template>

<style scoped>
</style>

Home.vue:

<script setup>
    import {ref} from 'vue'
    import {useRouter, useRoute} from 'vue-router'

    let route = useRoute()
    let router = useRouter()

    let username = window.localStorage.getItem('username')

    let logout = () => {
        //清楚 localStorge 中的 username
        window.localStorage.removeItem('username')
        // 动态路由到登录页
        router.push('/login')
    }
</script>

<template>
  <div>
    <h1> Home 页面</h1>
    <h3>欢迎{{username}}登录</h3>
    <button @click="logout()">退出登录</button>
  </div>
</template>

<style scoped>
</style>

App.vue:

<script setup>

</script>

<template>
  <div>
    <router-view></router-view>
  </div>
</template>

<style scoped>
</style>

定义 routers.js:

import { createRouter, createWebHashHistory } from "vue-router";
import Home from "../components/Home.vue";
import Login from "../components/Login.vue";

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: "/home",
      component: Home,
    },
    {
        path:"/",
        component:Home
    },
    {
        path:"/login",
        component:Login
    }
  ],
});

// 设置路由的全局前置首位
router.beforeEach(
    (to,from,next) => {
        console.log(`从哪里来:${from.path},到哪里去${to.path}`)
        if (to.path == '/login') {
            next()
        } else {
            let username = window.localStorage.getItem("username")
            if (null != username) {
                next()
            } else {
                next("/login")
            }
        }
    }
)

// 设置路由的全局后置首位
router.afterEach(
    (to, from) => {
        console.log(`从哪里来:${from.path},到哪里去${to.path}`)
    }
)

// 对外暴露路由对象
export default router

修改 main.js

import { createApp } from 'vue'
import App from './App.vue'

import router from './routers/router'
let app = createApp(App)
app.use(router)
app.mount('#app')

测试无误~

补充:

路由传参:useRoute,编程式路由:useRouter:

完!

更多推荐