• Vue路由(vue-router)


    一、Vue路由的相关概念

           1、路由(routing):是指从源到目的地时,决定端到端路径的决策过程。

           2、前端路由:即由前端来维护一个路由规则。实现模式有两种。

               (1)利用URL的Hash模式:就是常说的锚点,JavaScript通过hashChange事件来监听URL的改变。(IE7及以下版本需要使用轮询)

               (2)利用HTML5的History模式:它使用URL看起来像普通网站一样,以”/”分割,没有”#”,但是页面并没有跳转。这种模式需要服务器端支持,服务端在接收到所有的请求后,都指向同一个HTML文件,不然会出现页面错误

          3、VueRouter路由:路由就是根据一个请求路径选中一个组件进行渲染的决策过程。Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

                route:首先它是个单数,译为路由,可以理解为单个路由或者某一个路由;例如Home按钮  => home内容, 这是一条route,  about按钮 => about 内容, 这是另一条路由。

                routes:它是个复数,表示多个的集合才能为复数;可以理解为多个路由的集合,官方定义routes是一个数组;所以routes表示多个路由(route)的集合;

                router:译为路由器,上面都是路由,这个是路由器,可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个;举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由;

                VueRouter包括三个主要组成部分 —— VueRouter、router-view和 router-link

                    

                            VueRouter :路由器类,根据路由请求在路由视图中动态渲染选中的组件

                            router-link :路由链接组件,声明用以提交路由请求的用户接口

                            router-view:路由视图组件,负责动态渲染路由选中的组件          

                  4、vue-router(4.0)的常用函数:

                           createRouter函数:创建路由器

                           createWebHashHistory函数:创建Hash模式

                           createWebHistory函数:创建History模式

    1. 例如:
    2. const router = createRouter({
    3. history: createWebHashHistory(),
    4. routes: [
    5. //...
    6. ],})

    二、vue-router的基本应用(Vue3.0)

            1、安装vue-router

                        npm install vue-router

            2、创建路由配置文件

    1. import {createRouter, createWebHashHistory} from "vue-router";
    2. import Home from "@/components/Home";
    3. import About from "@/components/About";
    4. const routes= [
    5. {
    6. path: '/home',
    7. component: Home,
    8. name: 'home'
    9. },
    10. {
    11. path: '/about',
    12. component: About,
    13. name: 'about'
    14. }
    15. ]
    16. const router = createRouter({
    17. routes,
    18. history:createWebHashHistory()
    19. })
    20. export default router;

             3、声明路由请求接口

                  路由链接组件(router-link)为用户提供了提交路由请求的交互接口。 使用to属性来声明链接组件的目标路径。当用户点击链接组件时,组件向路由器提交向目标路径的路由请求。在模板中,使用<router-link> 标签声明路由链接元素。

                   例如,下面的示例声明了一个目标路径为/about的路由链接:

                        <router-link to="/about">ABOUT</router-link>

             4、声明路由出口

                  路由视图组件(router-view)为路由器($router)提供了所选中组件的渲染出口。在模板中,使用标签<router-view>声明路由视图元素。

                 例如,下面示例在模板中声明了一个路由视图:

                         <router-view></router-view>

                 路由链接组件默认渲染为一个a元素,因此在视图DOM中,上面的模板对应于 DOM结构:

                          <a href="...">ABOUT</a>

              例如:在App.vue中配置:

    1. <template>
    2. <div class="link">
    3. <router-link to="/home">Home</router-link>
    4. &nbsp; &nbsp; &nbsp; &nbsp;
    5. <router-link to="/about">About</router-link>
    6. </div>
    7. <img alt="Vue logo" src="./assets/logo.png">
    8. <router-view></router-view>
    9. </template>

                在main.js文件中使用路由

                

     三、动态路由匹配

           1、什么是动态路由?

              是指路由器能够自动地建立自己的路由表,并且能够根据实际情况的变化适时地进行调整。可以在一个路由中设置多段“路径参数”,对应的值都会设置到$route.params中。例如:

            2、适用场景

              (1)比如一个网站或者后台管理系统中,在我们登录之后,通常会有一个欢迎回来,XXX之类的提示语,这个我们就可以通过动态路由来实现这个效果;

              创建user.vue组件

    1. <template>
    2.     <div>
    3.         <h1>user</h1>
    4.        <!-- 这里可以通过$route.params.name来获取路由的参数 -->
    5.         <p>欢迎回来,{{$route.params.name}}</p>
    6.     </div>
    7. </template>
    8. <script>
    9.     export default {
    10.         data () {
    11.             return {
    12.                 msg"我是page1组件"
    13.             }
    14.         }
    15.     }
    16. </script>

              修改App.vue

    1. <!-- 添加两个router-link标签 -->
    2.     <div>
    3.       <router-link to="/user/项羽">动态路由--项羽</router-link>
    4.       <router-link to="/user/刘邦">动态路由--刘邦</router-link>
    5.     </div>

              修改router.js

    1. //引入user组件
    2. import user from '../components/user'
    3. //使用冒号标记,当匹配到的时候,参数值会被设置到this.$route.params中
    4.     {
    5.         path'/user/:name',
    6.         component: user
    7.     }

            动态路由匹配给我们提供了方便,使得我们通过配置一个路由来实现页面局部修改的效果,给用户造成一种多个页面的感觉

           3、查询参数:URL中带有查询参数的形式(/book?Id=1),根据查询参数向服务器请求数据。在单页应用程序开发中,也支持路径中的查询参数。

          Book.vue

    1. <template>
    2. <div>
    3. <p>图书ID: {{ $route.query.id }}</p>
    4. </div>
    5. </template>
    6. <script>
    7. export default {
    8. name: "Book"
    9. }
    10. </script>

           App.vue

       

           4、通配符匹配:常规参数只会匹配以/分隔的URL片段中的字符。如果想匹配任意路径,可以使用通配符(*)。例如:

          {

              path: ‘*’  //将匹配所有路径

           }

          {

              path: ‘/user-*’ //匹配以/user-开头的任意路径

            }

          当使用通配符路由时,要确保路由的顺序时正确的,即含有通配符的路由应该放在最后。路由{ path: ‘*’ }通常用于客户端404错误

     四、嵌套路由

             比如当我们进入主页之后有分类,然后当选择其中一个分类之后进入对应的详情,这个时候我们就可以用到嵌套路由;官方文档中给我们提供了一个children属性,这个属性是一个数组类型,里面实际放着一组路由;这个时候父子关系结构就出来了,所以children属性里面的是路由相对来说是children属性外部路由的子路由;

             在asssets目录下新建一个book.js文件存放图书数据

    1. export default [
    2. {
    3. id: 1,
    4. title: 'Vue.js无难事',
    5. desc: '前端框架经典图书'
    6. },
    7. {
    8. id: 2,
    9. title: 'React.js工程师宝典',
    10. desc: '前端框架经典图书'
    11. },
    12. {
    13. id: 3,
    14. title: 'Go语言程序设计',
    15. desc: '最流行的脚本语言'
    16. }
    17. ]

          Books.vue

    1. <template>
    2. <div>
    3. <h3>图书列表</h3>
    4. <ul>
    5. <li v-for="book in books" :key="book.id" style="list-style-type: none">
    6. <router-link :to="'/books/book/' +book.id">{{ book.title }}</router-link>
    7. </li>
    8. </ul>
    9. <router-view></router-view>
    10. </div>
    11. </template>
    12. <script>
    13. import Books from '@/assets/books'
    14. export default {
    15. name: "Books",
    16. data() {
    17. return {
    18. books: Books
    19. }
    20. }
    21. }
    22. </script>
    23. <style scoped>
    24. </style>

            路由文件: index.js

    1. import {createRouter, createWebHistory} from "vue-router";
    2. const routes = [
    3. {
    4. path: '/books',
    5. name: 'books',
    6. component: ()=> import('../components/Books'),
    7. children: [
    8. {
    9. path: '/books/book/:id',
    10. component: ()=> import('../components/Book')
    11. }
    12. ]
    13. }
    14. ]
    15. export default createRouter({
    16. routes,
    17. history: createWebHistory()
    18. })

               App.vue

            

    五、命名路由

            有时通过一个名称来标识路由会更方便,特别是在链接到路由,或者是执行导航时。可以创建Router实例时,在routes选项中为路由设置名称

       修改上例:创建两个组件(News、Video)

       修改路由文件:router/index.js

    1. import {createRouter, createWebHistory} from "vue-router";
    2. const routes = [
    3. {
    4. path: '/',
    5. redirect: {
    6. name: 'news'
    7. }
    8. },
    9. {
    10. path: '/news',
    11. name: 'news',
    12. component: ()=> import('../components/News')
    13. },
    14. {
    15. path: '/books',
    16. name: 'books',
    17. component: ()=> import('../components/Books'),
    18. children: [
    19. {
    20. path: '/books/book/:id',
    21. component: ()=> import('../components/Book')
    22. }
    23. ]
    24. },
    25. {
    26. path: '/video',
    27. name: 'video',
    28. component: ()=> import('../components/Video')
    29. }
    30. ]
    31. export default createRouter({
    32. routes,
    33. history: createWebHistory()
    34. })

              修改:App.vue

              注意:to属性的值是表达式,所以需要使用v-bind指令

    六、命名视图

            即给<router-view>设置名称

            没有设置名称的<router-view>默认为default。可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。例如

            路由出口:

    1. <router-view  name="header"></router-view>
    2. <router-view  name="sidebar"></router-view>

          路由配置:          

    1. routes: [
    2.              path: '/',
    3.              components: {
    4.                   defaultMain
    5.                   header:Header,
    6.                   sidebar:Sidebar
    7.              }
    8.          ]

    修改上例:Books.vue组件

     修改上例:router/index.js文件

    五、路由导航两种方式:

            标签导航:标签导航<router-link><router-link>是通过转义为<a></a>标签进行跳转,其中router-link标签中的to属性会被转义为a标签中的href属性;

               //跳转到名为user路由,并传递参数userId

               <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

             编程式导航:我们可以通过this.$router.push()这个方法来实现编程式导航,当然也可以实现参数传递,这种编程式导航一般是用于按钮点击之后跳转

                  this.$router.push({ name: 'user', params: { userId: 123 }})

      例如:修改上例路由文件router/index.js

     六、导航守卫:

       主要用于在导航的过程中重定向或者取消路由、或者添加权限验证、数据获取等业务逻辑。导航守卫分为三类:全局守卫路由独享的守卫组件内守卫,可以用于路由导航过程中的不同阶段。每一个导航守卫都有三个参数:to、from和next (router、afterEach除外)  

          1、全局守卫:分为全局前置守卫、全局解析守卫、全局后置钩子。

           (1)全局前置守卫:使用router.beforeEach注册。当一个导航触发时,全局前置守卫按照路由创建的顺序调用。

           在使用全局前置守卫时,要确保next函数的正确调用。例如:

           

    1. router.beforeEach((to,from,next) => {
    2. if( !isAuthenticated){
    3. next(‘/login’)
    4. }else{
    5. next();
    6. }
    7. })

    示例:登录验证

        Login.vue

    1. <template>
    2. <div>
    3. <div>
    4. <h3>用户登录</h3>
    5. <div>
    6. <label>
    7. 用户名:
    8. <input type="text" v-model.trim="username"/>
    9. </label>
    10. <br><br>
    11. <label>
    12. 密&nbsp;&nbsp;&nbsp;码:
    13. <input type="password" v-model.trim="password"/>
    14. </label>
    15. <br><br>
    16. <input type="submit" value="登录" @click.prevent="login"/>
    17. </div>
    18. </div>
    19. <h3>{{ info }}</h3>
    20. </div>
    21. </template>
    22. <script>
    23. export default {
    24. name: "Login",
    25. data(){
    26. return {
    27. username: "",
    28. password: "",
    29. info: "" //用于保存登录失败后的提示信息
    30. }
    31. },
    32. methods: {
    33. login() {
    34. if ("lisi" == this.username && "12345" == this.password){ //用户名合法
    35. sessionStorage.setItem("isAuth",true); //写入session信息
    36. this.info = "";
    37. if (this.$route.query.redirect){ //如果存在查询参数
    38. let redirect = this.$route.query.redirect;
    39. this.$router.replace(redirect);
    40. }else{
    41. //否则跳转至首页
    42. this.$router.replace('/home')
    43. }
    44. }else{
    45. sessionStorage.setItem("isAuth",false);
    46. this.username = "";
    47. this.password = "";
    48. this.info = "用户名或密码错误"
    49. }
    50. }
    51. }
    52. }
    53. </script>

     路由配置文件router/index.js

    1. import {createRouter,createWebHistory} from "vue-router";
    2. import Login from "@/components/Login";
    3. import Home from "@/components/Home";
    4. const router = createRouter({
    5. history: createWebHistory(),
    6. routes: [
    7. {
    8. path: '/home',
    9. name: 'home',
    10. component: Home
    11. },
    12. {
    13. path: '/login',
    14. name: 'login',
    15. component: Login
    16. }
    17. ]
    18. });
    19. //前置路由守卫
    20. router.afterEach((to,from,next)=>{
    21. //判断目标路由是否是'/login',如果是,则直接调用next()方法
    22. if (to.path == '/login'){
    23. next();
    24. }else{
    25. //否则判断用户是否已经登录
    26. if (sessionStorage.getItem('isAuth')){ //若用户已经登录,则执行next()跳转
    27. next();
    28. }else{
    29. /*若用户访问的是受保护的资源,且没有登录,则跳转到登录页面
    30. 并将当前路由的完整路径作为查询参数传给Login组件,以便登录成功后返回先前的页面
    31. */
    32. next({
    33. path: '/login',
    34. query: {
    35. redirect: to.fullPath
    36. }
    37. })
    38. console.log(to.fullPath)
    39. }
    40. }
    41. })
    42. export default router;

    App.vue

    1. <template>
    2. <img alt="Vue logo" src="./assets/logo.png">
    3. <router-link :to="{name: 'login'}" class="login">登录</router-link>
    4. <router-view></router-view>
    5. </template>
    6. <script>
    7. export default {
    8. name: 'App',
    9. components: {
    10. }
    11. }
    12. </script>
    13. <style>
    14. .login{
    15. display: flex;
    16. justify-content: center;
    17. }
    18. </style>

    App.vue

    1. <template>
    2. <img alt="Vue logo" src="./assets/logo.png">
    3. <router-link :to="{name: 'login'}" class="login">登录</router-link>
    4. <router-view></router-view>
    5. </template>
    6. <script>
    7. export default {
    8. name: 'App',
    9. components: {
    10. }
    11. }
    12. </script>
    13. <style>
    14. .login{
    15. display: flex;
    16. justify-content: center;
    17. }
    18. </style>

                  (2)全局解析守卫:使用router.beforeResole注册。是在导航被确认之前,在所有组件内守卫和异步路由组件被解析之后被调用

                  (3)全局后置钩子:使用router.afterEach注册。与守卫不同的是,全局后置钩子不接受next函数,也不会改变导航

              2、路由独享的守卫:是在routes配置的路由对象中直接定义的beforeEnter守卫。例如:

         3、组件内守卫:在组件内使用beforeRouteUpdate、beforeRouteEnter、beforeRouteLeave定义的守卫

     

     

  • 相关阅读:
    具身智能(Embodied AI)
    vue3开发快速入门
    百度文心一言
    TOWE模块化积木式定制PDU的应用优势
    提高IT运维效率,深度解读京东云AIOps落地实践(异常检测篇)
    Servlet学生管理系统(萌新练手版)
    【MySQL】20-MySQL如何创建和管理表超详细汇总
    8、数据结构-字符串、编码集
    前后端分离:停车管理系统(Java后端,vue前端)
    最优控制理论 九、Bellman动态规划法用于最优控制
  • 原文地址:https://blog.csdn.net/m0_37911706/article/details/125491117