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

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>
  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue2中,路由守卫是通过全局的导航守卫函数来实现的,包括`beforeEach`、`beforeResolve`和`afterEach`等。这些守卫函数可以在路由跳转前、解析前和跳转后执行特定的逻辑。 而在Vue3中,引入了Composition API,路由守卫使用也有所不同。Vue-RouterVue3中提供了两个Composition API用于路由守卫,即`onBeforeRouteLeave`和`onBeforeRouteUpdate`。这两个函数只能在`setup`函数中使用,并且可以在组件内部实现相应的逻辑。 举个例子,比如在Vue2中,可以使用`beforeEach`全局导航守卫函数来进行路由跳转前的验证。而在Vue3中,可以使用`onBeforeRouteLeave`来实现类似的功能。具体代码如下: Vue2中的全局导航守卫: ```javascript router.beforeEach((to, from, next) => { // 验证逻辑 if (to.meta.requiresAuth && !isAuthenticated) { next('/login'); } else { next(); } }); ``` Vue3中的路由守卫使用Composition API: ```javascript import { onBeforeRouteLeave } from 'vue-router'; export default { setup() { onBeforeRouteLeave((to, from) => { // 验证逻辑 if (to.meta.requiresAuth && !isAuthenticated) { router.push('/login'); } }); } } ``` 总的来说,Vue2和Vue3的路由守卫都实现了类似的功能,但在使用方式和语法上有所区别。Vue2使用全局导航守卫函数,而Vue3使用Composition API中的`onBeforeRouteLeave`和`onBeforeRouteUpdate`函数来实现路由守卫。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue 路由缓存 路由嵌套 路由守卫 监听物理返回操作](https://download.csdn.net/download/weixin_38739950/12924360)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [vue2 和 vue3 的 路由守卫](https://blog.csdn.net/lzfengquan/article/details/125403486)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [vue2.0 实现导航守卫路由守卫)](https://download.csdn.net/download/weixin_38692969/13659362)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMonkey-D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值