Vue组件:Vue Router以及路由守卫,含路由的基本使用,配置,路由传参,导航方式,缓存;路由守卫的三种用法

发布时间:2023年12月28日

Vue Router

vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目中组件的切换。点击页面的导航链接时,不会刷新页面,只会局部更新

基础使用

使用步骤:

  1. 安装vue-router,命令

    npm i vue-router@3.2.0
    
  2. 在src同级目录下创建router目录,并创建路由的js配置文件,index.js

  3. 创建组件(多个)

    Home组件

    <template>
      <div>
        <h1>我是Home组件</h1>
      </div>
    </template>
    
    <script>
    export default {
      name: "Home"
    }
    </script>
    

    About组件

    <template>
      <div>
        <h1>我是About组件</h1>
      </div>
    </template>
    
    <script>
    export default {
      name: "About"
    }
    </script>
    
  4. 编写路由的配置文件index.js

    '/':默认展示页面

    // 1.引入路由的核心库
    import VueRouter from "vue-router";
    // 2.引入要被路由的组件
    import Home from "@/components/Home";
    import About from "@/components/About";
    
    //  3.创建并暴露路由
    export default new VueRouter({
        routes:[
            {
                path:'/', 
                component:Home
            },
            {
                path:'/about',
                component:About
            },
          	{
                path:'/home',
                component:Home
            }
    })
    
  5. 在main.js配置路由

    import Vue from 'vue'
    import App from './App.vue'
    // 引入路由核心库
    import VueRouter from "vue-router";
    // 引入路由配置文件
    import router from './router/index';
    
    Vue.config.productionTip = false
    Vue.use(VueRouter)
    
    new Vue({
      render: h => h(App),
      router   // vue加载路由
    }).$mount('#app')
    
  6. 在App.vue中注册组件,并使用

    <template>
      <div id="app">
        <router-link to="/home">Home</router-link>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <router-link to="/about">About</router-link>
        <hr/>
        <!-- 准备被路由组件显示的位置-->
        <router-view></router-view>
      </div>
    
    </template>
    
    <script>
    
    export default {
      name: 'App',
      components: {
      }
    }
    </script>
    

多级路由

组件中包含组件,形成组件之间的嵌套,路由之间形成层级关系

  1. 创建组件,eg:News组件和Message组件

    News组件:

    <template>
      <div>
        <ul>
          <li>唱歌</li>
          <li>跳舞</li>
          <li>篮球</li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      name: "News"
    }
    </script>
    

    Message组件:

    <template>
      <div>
        <ol>
          <li>
            <a href="#">测试数据1</a>
          </li>
          <li>
            <a href="#">测试数据2</a>
          </li>
          <li>
            <a href="#">测试数据3</a>
          </li>
        </ol>
      </div>
    </template>
    
    <script>
    import {nanoid} from 'nanoid';
    
    export default {
      name: "Message"
    }
    </script>
    
  2. 更改路由组件的配置,在父组件的路由下配置子组件路由

    注意:二级路径不加/

    // 引入路由的核心库
    import VueRouter from "vue-router";
    // 引入要被路由的组件
    import Home from "@/components/Home";
    import About from "@/components/About";
    import News from "@/components/News";
    import Message from "@/components/Message";
    import Detial from "@/components/Detail";
    
    //  创建并暴露路由
    export default new VueRouter({
        routes:[
            {
                path:'/',
                component:Home
            },
            {
                path:'/about',
                component:About
            },
            {
                path:'/home',
                component:Home,
                children:[
                    {
                        path:'news', /* 二级路径不写/ */
                        component:News
                    },
                    {
                        path:'message',
                        component:Message
                    }
                ]
            }
        ]
    })
    
  3. 父组件中展示内容,父组件Home

    多级路由跳转要写全路径

    	<template>
      <div>
        <h1>我是Home组件</h1>
        <router-link to="/home/news">News</router-link>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <router-link to="/home/message">Message</router-link>
        <hr/>
        <!-- Home组件中路由显示的位置 -->
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    export default {
      name: "Home"
    }
    </script>
    

路由组件传参

加入现在Message组件要给它的子组件Detail组件传参

  1. 路由配置文件中配置

    // 引入路由的核心库
    import VueRouter from "vue-router";
    // 引入要被路由的组件
    import Home from "@/components/Home";
    import About from "@/components/About";
    import News from "@/components/News";
    import Message from "@/components/Message";
    import Detial from "@/components/Detail";
    
    //  创建并暴露路由
    export default new VueRouter({
        routes:[
            {
                path:'/',
                component:Home
            },
            {
                path:'/about',
                component:About
            },
            {
                path:'/home',
                component:Home,
                children:[
                    {
                        path:'news', /* 二级路径不写/ */
                        component:News
                    },
                    {
                        path:'message',
                        component:Message,
                        children:[
                            {
                                path:'detail',
                                component:Detial
                            }
                        ]
                    }
                ]
            }
        ]
    })
    
  2. Message组件传递

    方式1:

    使用模板字符串,并且给to属性添加:,拼接url,${}的形式带参

    <template>
      <div>
        <ol>
          <li v-for="msg in msgList" :key="msg.id">
          <router-link :to="`/home/message/detail?		id=${msg.id}&title=${msg.title}`">{{msg.title}}</router-link>
          </li>
        </ol>
        <hr/>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import {nanoid} from 'nanoid';
    
    export default {
      name: "Message",
      data(){
        return{
          msgList:[
            {id:nanoid(),title:'消息数据A'},
            {id:nanoid(),title:'消息数据B'},
            {id:nanoid(),title:'消息数据C'}
          ]
        }
      }
    }
    </script>
    

    方式2:

    改为对象形式的传参

    <template>
      <div>
        <ol>
          <li v-for="msg in msgList" :key="msg.id">
            <router-link :to="{
                  path:'/home/message/detail',
                  query:{
                    id:msg.id,
                    title:msg.title
                  }
            }" >
              {{msg.title}}
            </router-link>
          </li>
        </ol>
        <hr/>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import {nanoid} from 'nanoid';
    
    export default {
      name: "Message",
      data(){
        return{
          msgList:[
            {id:nanoid(),title:'消息数据A'},
            {id:nanoid(),title:'消息数据B'},
            {id:nanoid(),title:'消息数据C'}
          ]
        }
      }
    }
    </script>
    
  3. Detail子组件中接收数据

    使用$route属性,因为参数在url中所以要使用query,再.上参名即可传参

    <template>
      <div>
        <ul>
          <li>消息编号:{{$route.query.id}}</li>
          <li>消息标题:{{$route.query.title}}</li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      name: "Detail"
    }
    </script>
    

命名路由

跳转时路径较长,使用命名路由简化跳转路径

实现步骤:

  1. 在路由配置中,给路由添加一个name属性,index.js

    例如上述案例中给Detail组件添加一个命名路由,detail的路由配置如下

    {
      path:'message',
        component:Message,
          children:[
            {
              path:'detail',
              name:'xq',   // 添加命名
              component:Detial
            }
          ]
    }
    
  2. 组件使用对象形式的跳转

    使用name属性进行跳转

    <template>
      <div>
        <ol>
          <li v-for="msg in msgList" :key="msg.id">
            <router-link :to="{
                  // path:'/home/message/detail',
                  name:'xq',     // 用name属性跳转
                  query:{
                    id:msg.id,
                    title:msg.title
                  }
            }" >
              {{msg.title}}
            </router-link>
          </li>
        </ol>
        <hr/>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import {nanoid} from 'nanoid';
    
    export default {
      name: "Message",
      data(){
        return{
          msgList:[
            {id:nanoid(),title:'消息数据A'},
            {id:nanoid(),title:'消息数据B'},
            {id:nanoid(),title:'消息数据C'}
          ]
        }
      }
    }
    </script>
    

路由的params参数

作用:路由之间进行参数传递,因此url中的参数名

实现步骤:

  1. 在路由配置中添加占位符,index.js中

    {
      path:'message',
        component:Message,
          children:[
            {
              path:'detail/:id/:title',
              name:'xq',
              component:Detial
            }
          ]
    }
    

    给path添加占位符,:参数名

  2. 改变传参对象,query传参改为params传参,Message组件

    使用params传参

    情况1:对象形式

    <template>
      <div>
        <ol>
          <li v-for="msg in msgList" :key="msg.id">
            <router-link :to="{
                  name:'xq',     // 用name属性跳转
                  params:{
                    id:msg.id,
                    title:msg.title
                  }
            }" >
              {{msg.title}}
            </router-link>
          </li>
        </ol>
        <hr/>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import {nanoid} from 'nanoid';
    
    export default {
      name: "Message",
      data(){
        return{
          msgList:[
            {id:nanoid(),title:'消息数据A'},
            {id:nanoid(),title:'消息数据B'},
            {id:nanoid(),title:'消息数据C'}
          ]
        }
      }
    }
    </script>
    

    情况2:字符串形式路径

    <router-link :to="`/home/message/detail/${msg.id}/${msg.title}`"> {{msg.title}}
    </router-link>
    
  3. 改变数据接收,query接收改为params接收,Detail组件

    使用params接收

    <template>
      <div>
        <ul>
          <li>消息编号:{{$route.params.id}}</li>
          <li>消息标题:{{$route.params.title}}</li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      name: "Detail"
    }
    </script>
    

props配置

作用:简化接收参数

实现步骤:

  1. 路由配置中配置props属性

    方式一:固定值方式

    props:{id:xxx,titel:...}
    

    方式二:启用方式

    {
      path:'message',
        component:Message,
          children:[
            {
              path:'detail/:id/:title',
              name:'xq',
              component:Detial,
              props:true   //	启用方式
            }
          ]
    }
    

    方式三:决定来源的方式

    {
      path:'message',
        component:Message,
          children:[
            {
              path:'detail/:id/:title',
              name:'xq',
              component:Detial,
              props($route){
                return {
                  id : $route.params.id,  //params/query  取决于来源于哪
                  title : $route.params.title
                }
              }
            }
          ]
    }
    
  2. 传参组件中params传参

    <router-link :to="{
                  name:'xq',     // 用name属性跳转
                  params:{
                    id:msg.id,
                    title:msg.title
                  }
            }" >
      {{msg.title}}
    </router-link>
    
  3. 接收组件中添加props接收,通过插值表达式使用

    <template>
      <div>
        <ul>
          <li>消息编号:{{id}}</li>
          <li>消息标题:{{title}}</li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      name: "Detail",
      props:['id','title']
    }
    </script>
    

浏览器历史记录的两种写入模式

在Home组件中添加前进后退按钮

<template>
  <div>
    <h1>我是Home组件</h1>
    <router-link to="/home/news">News</router-link>
    &nbsp;&nbsp;&nbsp;&nbsp;
    <router-link to="/home/message">Message</router-link>
    <button @click="back">后退</button>
    <button @click="forward">前进</button>
    <hr/>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "Home",
  methods:{
    back(){
      this.$router.back();    // $router : main.js中的名字
    },
    forward(){
      this.$router.forward();
    }
  }
}
</script>

在Message组件中添加模式

<!-- 可以写push 或者 replace 模式 -->
<router-link push :to="{       
              // path:'/home/message/detail',
              name:'xq',
              params:{
                id:msg.id,
                title:msg.title
              }
        }" >
    {{msg.title}}
</router-link>
  1. push:追加历史记录

    记录历史记录,一步一步回退

  2. replace:替换当前历史记录

    不保留历史记录,直接退回上个路由

导航方式

  1. 声明式

    上例中浏览器的写入模式演示的就是声明式的导航方式

    <!-- 可以写push 或者 replace 模式 -->
    <router-link push :to="{       
                  // path:'/home/message/detail',
                  name:'xq',
                  params:{
                    id:msg.id,
                    title:msg.title
                  }
            }" >
        {{msg.title}}
    </router-link>
    
  2. 编程式

    编程式绑定事件,传参通过()方式传递,方法中可以采用push或replace方式,方法中给一个配置对象,跳转地址,参数等

    <template>
      <div>
        <ol>
          <li v-for="msg in msgList" :key="msg.id">
              <button @click="goDetail(msg.id,msg.title)">{{msg.title}}</button>
          </li>
        </ol>
        <hr/>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import {nanoid} from 'nanoid';
    
    export default {
      name: "Message",
      data(){
        return{
          msgList:[
            {id:nanoid(),title:'消息数据A'},
            {id:nanoid(),title:'消息数据B'},
            {id:nanoid(),title:'消息数据C'}
          ]
        }
      },
      methods:{
        goDetail(id,title){
          this.$router.push({
            name:'xq',
            params:{
              id:id,
              title:title
            }
          })
        }
      }
    }
    </script>
    

缓存

  1. News组件中有输入框

    <template>
      <div>
        <ul>
          <li>唱歌 <input type="text"></li>
          <li>跳舞 <input type="text"></li>
          <li>篮球 <input type="text"></li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      name: "News"
    }
    </script>
    
  2. Message组件有输入框

    <template>
      <div>
        <ol>
          <li v-for="msg in msgList" :key="msg.id">
            <button @click="goDetail(msg.id,msg.title)">{{msg.title}}</button>
            <input type="text">
          </li>
        </ol>
        <hr/>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import {nanoid} from 'nanoid';
    
    export default {
      name: "Message",
      data(){
        return{
          msgList:[
            {id:nanoid(),title:'消息数据A'},
            {id:nanoid(),title:'消息数据B'},
            {id:nanoid(),title:'消息数据C'}
          ]
        }
      },
      methods:{
        goDetail(id,title){
          this.$router.push({
            name:'xq',
            params:{
              id:id,
              title:title
            }
          })
        }
      }
    }
    </script>
    
  3. 想要输入框的输入内容在跳转组件之后仍存在,需要给Home.vue父组件添加缓存

    <template>
      <div>
        <h1>我是Home组件</h1>
        <router-link to="/home/news">News</router-link>
        &nbsp;&nbsp;&nbsp;&nbsp;
        <router-link to="/home/message">Message</router-link>
        <hr/>
        <keep-alive>
          <router-view></router-view>
        </keep-alive>
      </div>
    </template>
    
    <script>
    export default {
      name: "Home"
    }
    </script>
    

    <keep-alive></keep-alive>标签包裹<router-view></router-view>

    指定组件缓存:include="指定缓存组件的组件名"

    <keep-alive include="News">
      <router-view></router-view>
    </keep-alive>
    

    指定多组件缓存::include="['组件名','组件名'...]"

    <keep-alive :include="['News','Message']">
      <router-view></router-view>
    </keep-alive>
    

在缓存的组件中添加缓存激活/失活生命周期函数

激活状态:activated(){}

失活状态:deactivated(){}

eg:News组件

<template>
  <div>
    <ul>
      <li>唱歌 <input type="text"></li>
      <li>跳舞 <input type="text"></li>
      <li>篮球 <input type="text"></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "News",
  activated() {
    console.log("组件激活")
  },
  deactivated() {
    console.log("组件失活")
  }
}
</script>

路由守卫

类似于过滤器的作用

全局路由守卫

全局路由守卫 :全部的路由都会执行

  1. 前置路由守卫

    路由配置文件中配置路由守卫,将创建路由对象,并配置路由守卫,最后将路由对象暴露

    // 引入路由的核心库
    import VueRouter from "vue-router";
    // 引入要被路由的组件
    import Home from "@/components/Home";
    import About from "@/components/About";
    import News from "@/components/News";
    import Message from "@/components/Message";
    import Detial from "@/components/Detail";
    
    //  创建并暴露路由
    const router =  new VueRouter({
        routes:[
            {
                path:'/',
                component:Home
            },
            {
                path:'/about',
                component:About
            },
            {
                path:'/home',
                component:Home,
                children:[
                    {
                        path:'news', /* 二级路径不写/ */
                        component:News
                    },
                    {
                        path:'message',
                        component:Message,
                        children:[
                            {
                                path:'detail/:id/:title',
                                name:'xq',
                                component:Detial,
                                props:true
                            }
                        ]
                    }
                ]
            }
        ]
    })
    
    // 全局路由守卫 
    // 1.前置路由守卫
    // 箭头函数三个参数,to:去哪里 from:从哪里来  next:执行next()才放行,不执行则拦截
    router.beforeEach((to, from, next)=>{
        console.log(to,from);
        next();
    })
    export default router;
    
  2. 后置路由守卫

    // 2.后置路由首位
    // 箭头函数两个参数,to:去往哪里  from:从哪里来
    router.afterEach((to, from)=>{
        console.log(to);
        console.log(from);
    })
    

独享路由守卫

针对于某个路由的守卫,再路由配置中添加独享路由守卫,例如给detail添加独享守卫

// 引入路由的核心库
import VueRouter from "vue-router";
// 引入要被路由的组件
import Home from "@/components/Home";
import About from "@/components/About";
import News from "@/components/News";
import Message from "@/components/Message";
import Detial from "@/components/Detail";

//  创建并暴露路由
const router =  new VueRouter({
    routes:[
        {
            path:'/',
            component:Home
        },
        {
            path:'/about',
            component:About
        },
        {
            path:'/home',
            component:Home,
            children:[
                {
                    path:'news', /* 二级路径不写/ */
                    component:News
                },
                {
                    path:'message',
                    component:Message,
                    children:[
                        {
                            path:'detail/:id/:title',
                            name:'xq',
                            component:Detial,
                            props:true,
                            // 独享路由守卫
                            beforeRouteEnter(to,from,next){
                                console.log(to);
                                console.log(from);
                                next();
                            }
                        }
                    ]
                }
            ]
        }
    ]
})
export default router;

组件路由守卫

组件内部的路由守卫

  1. 前置路由守卫
  2. 后置路由守卫,与全局路由守卫不同的是后置路由守卫有next()方法
<template>
  <div>
    <h1>我是About组件</h1>
  </div>
</template>

<script>
export default {
  name: "About",
  beforeRouteEnter(to,from,next){
    //组件前置路由守卫
    console.log(to);
    console.log(from);
    next();  // 执行放行
  },
  beforeRouteLeave(to,from,next){
    //组件后置路由守卫
    console.log(to);
    console.log(from);
    next();  // 组件后置路由守卫执行next()方法才会出去
  }
}
</script>
文章来源:https://blog.csdn.net/HakerDONG/article/details/135233228
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。