【Vue路由】

一、Vue的路由

1、路由

路由(routing):指从源页面到目的页面的决策过程

2、前端路由

前端路由:在前端页面中维护的路由规则

(1)hash:在地址中以’#'分隔页面

(2)history:在地址栏中以’/'分隔页面

※3、VueRouter路由

VueRouter路由:路由就是根据一个请求路径选中一个组件进行渲染的决策过程。是Vue官方推出的路由管理器

(1)route:表示单个路由

(2)routes:表示多个路由的集合。是一个数组,在这个数组中包含了多个的route

(3)router:译为路由器。可以理解为一个容器包含上述两个或理解为是route和routes的管理者

当用户点击某个按钮或超链接时,路由的查找过程:路由器 会去 路由集合 中查找对应的 路由

4、VueRouter的组成

(1)VueRouter类:维护的是一张路由表,根据路由的请求去渲染某个组件

(2)route-link:路由链接组件,类似于<a>标签。

(3)route-view:路由视图组件,路由出口,用于显示渲染的组件

5、vue-router常用的函数

(1)createRouter函数:创建路由器

(2)createWebHashHistory函数:创建hash模式的路由

(3)createWebHistory函数:创建history模式的路由

二、VueRouter的应用

1、安装vue-router

npm install vue-router

2、创建路由文件

(1)定义路由表:routes,在路由表中包含多个路由(route)

(2)创建路由器:router,在路由器中指定路由表(routes)以及路由模式(hash/history)

3、声明路由的请求接口

声明路由的请求接口:定义router-link,使用’to’属性声明路由的目标路径.

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

4、声明路由出口

声明路由出口:指定组件渲染的位置

格式<router-view></router-view>

⭐举例:

Home.vue组件代码段:

<template>
  <h2><h2>我是Home组件</h2></h2>
</template>

<script>
export default {
  name: "Home"
}
</script>

<style scoped>

</style>

About.vue组件代码段:

<template>
  <h2>我是About组件</h2>
</template>

<script>
export default {
  name: "About"
}
</script>

<style scoped>

</style>

routers目录下的router.js文件:

import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";
const rs = [   //定义路由表
    {
        path:'/home',
        component: Home,
        name: 'home'
    },
    {
        path:'/about',
        component: About,
        name: 'about'
    }
   
]

//定义路由器
const router = createRouter({
    routes:rs,
    history: createWebHistory()
})

//导出路由器
export default router

main.js代码段:

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from "./routers/router";

const app=createApp(App)
    app.use(router)
    app.mount('#app')

App.vue代码段:

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
<!--创建路由的链接组件(路由接口)-->
  <div>
    <router-link to="/home">Home</router-link>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <router-link to="/about">About</router-link>
  </div>
  <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
  <router-view></router-view>
</template>


在这里插入图片描述
在这里插入图片描述

三、动态路由

动态路由:是指路由器能够自动的建立自己的路由表,并且能够根据实际情况的变化适时的进行调整。

在路由中带有路由参数,路由参数会设置到"$route.params"中

1、动态路由的路径格式

动态路由的路径格式:/组件名/:参数名;在组件中通过’$route.params.参数名’获取参数

💥举例:

User.vue组件代码段:

<template>
<h2>User组件</h2>
  <p>欢迎回来,{{ $route.params.name }}</p>
</template>
<script>
export default {
  name: "User"
}
</script>

routers目录下的router.js文件:

import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
import User from "../components/User.vue";
const rs = [   //定义路由表
   {
        path: '/user/:name',
        component: User,
        name:'user'
    } 
]
//定义路由器
const router = createRouter({
    routes:rs,
    history: createWebHistory()
})

//导出路由器
export default router

App.vue代码段:

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
<!--创建路由的链接组件(路由接口)-->
  <div>
    <router-link to="/user/项羽">动态路由---项羽</router-link>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <router-link to="/user/刘邦">动态路由---刘邦</router-link>
 </div>
  <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
  <router-view></router-view>
</template>

在这里插入图片描述

在这里插入图片描述

2、在URL中带查询参数

在URL中带查询参数:/组件名?参数名1=参数值1&参数名2=参数值2…; 在组件中通过’$route.query.参数名’获取参数

💥举例:

App.vue代码段:

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
<!--创建路由的链接组件(路由接口)-->
  <div>
    <router-link to="/library?id=1">图书1</router-link>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <router-link to="/library?id=2">图书2</router-link>
</div>
  <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
  <router-view></router-view>

</template>

Library.vue组件代码段:

<template>
  <h2>Library组件</h2>
  <p>图书:{{ $route.query.id }}</p>
</template>

<script>
export default {
  name: "Library"
}
</script>

routers目录下的router.js文件:

import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
import Library  from "../components/Library.vue";
const rs = [   //定义路由表
  {
        path: '/library',
        component: Library,
        name:'library'
    }
]
//定义路由器
const router = createRouter({
    routes:rs,
    history: createWebHistory()
})

//导出路由器
export default router

3、通配符匹配

通配符匹配:'*'表示匹配所有路径。通常用于匹配前端的404页面

四、嵌套路由

嵌套路由:在组件中包含子组件的情况.vue官方提供children属性来定义这种嵌套关系。该属性是 一个数组,本质就是路由表

举一个实例:图书组件的嵌套

(1)图书列表组件:显示图书标题,每个标题都是链接组件,当用户点击链接组件(一级路由组件Books.vue)时,跳转到二级路由组件(Book.vue)

(2)图书组件:显示图书的详细信息

静态资源assets目录下的book.js文件:

export default [
    {
        id:1,
        title:'Vue.js无难事',
        desc:'前端框架经典图书'
    },
    {
        id:2,
        title:'React.js工程师宝典',
        desc:'前端框架经典图书'
    },
    {
        id:3,
        title:'Go语言程序设计',
        desc:'最流行的脚步语言'
    }
]

Books.vue组件代码段:

<template>
  <div>
    <h2>图书列表</h2>
    <ul>
      <li v-for="book in bookList" :key="book.id">
      <!--  :to  等价于v-bind:to  用来绑定变量-->
        <router-link :to="'/books/book/'+book.id">{{ book.title }}</router-link>
      </li>
    </ul>
  </div>
  <hr/>
  <div>
    <router-view></router-view>
  </div>
</template>
<script>
import books from "../assets/books";
export default {
  name: "Books",
  data(){
    return {
      bookList:books
    }
  }
}
</script>

<style scoped>
li{
  list-style-type: none;
  margin-top: 25px;
}
</style>

Book.vue组件代码段:


<template>
  <div>
    <p>图书ID{{book.id}}</p>
    <p>图书名称:{{ book.title }}</p>
    <p>描述:{{ book.desc }}</p>
  </div>
</template>

<script>
import books from "../assets/books";
export default {
  name: "Book",
  data(){
    return {
      book: {}
    }
  },
  created() {//获取第一次渲染时的数据,否则第一次渲染时$route对象得不到数据
    this.book = books.find((item)=>item.id == this.$route.params.id)
  },
  watch : {
    '$route':{  //监听路由参数的变化
      handler:function (to){
        this.book = books.find((item)=>item.id == this.$route.params.id)
      }
    }
  }
}
</script>


routers目录下的router.js文件:

注意:component: ()=>import(‘…/components/Books.vue’)另一种引入组件的写法

import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
const rs = [   //定义路由表
  {
        path: '/books',
        name: 'books',
        component: ()=>import('../components/Books.vue'),
        children: [{
            path: '/books/book/:id',
            component: ()=>import('../components/Book.vue')
        }]
    }
]
//定义路由器
const router = createRouter({
    routes:rs,
    history: createWebHistory()
})

//导出路由器
export default router

在这里插入图片描述
在这里插入图片描述

五、命名路由

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

例如:将上例中的App.vue修改后同样可以的到相同的跳转效果:

App.vue代码段:

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
<!--创建路由的链接组件(路由接口)-->
  <div>
    //<router-link to="/home">Home</router-link>
    //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    //<router-link to="/about">About</router-link>
    <router-link :to="{name:'home'}">Home</router-link>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <router-link :to="{name:'about'}">About</router-link>
  </div>
  <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
  <router-view></router-view>
</template>


在这里插入图片描述
在这里插入图片描述

六、命名视图

命名视图:给路由视图(<router-view>)一个名称,可以将组件渲染到指定名称的路由视图中

1、给路由视图添加name属性。如:

上例的books.vue代码段修改如下:

<template>
  <div>
    <h2>图书列表</h2>
    <ul>
      <li v-for="book in bookList" :key="book.id">
        <router-link :to="'/books/book/'+book.id">{{ book.title }}</router-link>
      </li>
    </ul>
  </div>
  <hr/>
  <div>
    <router-view name="test"></router-view>
  </div>
  <hr/>
  <div>
    <router-view name="bookDetail"></router-view>
  </div>
</template>

<script>
import books from "../assets/books";
export default {
  name: "Books",
  data(){
    return {
      bookList:books
    }
  }
}
</script>

<style scoped>
li{
  list-style-type: none;
  margin-top: 25px;
}
</style>

2、在路由表中,指定components属性的值。如:

routers目录下的router.js文件:

  {
        path: '/books',
        name: 'books',
        component: ()=>import('../components/Books.vue'),
        children: [{
            path: '/books/book/:id',
            //component: ()=>import('../components/Book.vue')
            components:{
            test:()=>import('../components/Book.vue')
            }
        }]
    }

因为指定的路由视图是test,所以将会渲染到视图name为test上,也就是第一个 横线的下方,第二个横线的上方。(如果为bookDetail,则在第二条线的下方)

在这里插入图片描述

七、导航守卫

1、路由导航的方式

(1)标签导航:<router-link :to="url"></router-link>
(2)编程式导航:this.$router.push(url)

2、导航守卫

导航守卫:在导航过程中由于权限验证、数据的获取等业务的需要,会出现页面的的重定向。

每个导航守卫都有三个参数(to,from,next)

‘to’:到哪里去
‘from’:从哪里来
‘next’:下一步去哪儿

(1)全局前置守卫:使用router.beforeEach注册,当一个导航触发时,前置守卫会按路由规则进行匹配调用。保证next函数能正常运行

💥举例:

Login.vue代码段:

<template>
  <div>
    <h2>用户登录</h2>
    <div>
      <label>
        UserName:
        <input type="text" v-model.trim="username"/>
      </label>
      <br><br>
      <label>
        PassWord:
        <input type="password" v-model.trim="password"/>
      </label>
      <br><br>
      <button type="button" @click.prevent="login">登录</button>
    </div>
    <h3>{{ info }}</h3>
  </div>
</template>

<script>
export default {
  name: "Login",
  data() {
    return {
      username: '',
      password: '',
      info: ''
    }
  },
  methods:{
    login(){
      if ("lisi"=== this.username && "12345"===this.password){ //合法用户,将用户信息写入页面缓存中
        sessionStorage.setItem("isAuth",true);
        this.info = "";

        if (this.$route.query.redirect){ //合法用户请求页面参数存在,就进行页面跳转
          let redirect = this.$route.query.redirect
          this.$router.replace(redirect);
        }else{
          this.$router.replace('/home');
        }
      }else{
        sessionStorage.setItem('isAuth',false)
        this.username = ''
        this.password = ''
        this.info = '用户名或密码错误'
      }
    }
  }
}
</script>
<style scoped>
</style>

Home.vue代码段:

<template>
<h2>我是首页</h2>
</template>

<script>
export default {
  name: "Home"
}
</script>

<style scoped>

</style>

main.js代码段(全局注册router):

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './routers/index.js'
const app = createApp(App)
app.use(router)
app.mount('#app')

router文件下的路由index.js文件:

import { createRouter,createWebHistory } from 'vue-router';
import Home from '../components/Home.vue';
import Login from '../components/Login.vue';

const rs = [
    {
        path:'/home',
        name:'home',
        component:Home
    },
    {
        path:'/login',
        name:'login',
        component:Login
    }
]

const router = createRouter({
    routes:rs,
    history:createWebHistory()
})
//创建导航前置守卫
router.beforeEach((to,from,next)=>{
    if(to.path == '/login'){ //若访问登录页面,则放行
        next();
    }else{
        if(sessionStorage.getItem('isAuth')){//若用户已登录,则放行
            next();
        }else{
            //用户没有登录,并且要访问受保护的资源,则将登录组件的地址告诉给next函数
            next({
                path:'/login',
                query:{
                    redirect:to.fullPath
                }
            })
            console.log(to.fullPath)
        }
    }
})
export default router;

App.vue代码段:

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
import Login from './components/Login.vue'
</script>

<template>

  <img src="/vite.svg" class="logo" alt="Vite logo" />
 <router-link :to="{name:'login'}" class="login">登录</router-link>
  <router-view> </router-view>

</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
.login{
  display: flex;
  justify-content:center;
}
</style>


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值