目录
1.路由
2.前端路由
3.VueRouter路由
4.VueRouter的组成
5.VueRouter常用的函数
二、VueRouter的使用
1、安装vue-router
2、创建路由文件
3、声明路由请求接口
4、声明路由出口
三、动态路由
1.动态路由的路径格式
2.在URL中带查询参数
3.通配符匹配
四、嵌套路由
五、命名路由
六、命名视图
1.给路由视图添加name属性
2.在路由表中,指定***ponents属性的值
七、导航守卫
1.路由导航的方式
2.导航守卫
一、Vue的路由
1.路由(routing)
路由是指从源页面到目的页面时,决定端到端路径的决策过程。
2.前端路由
前端路由即由前端来维护一个路由规则。实现模式有两种:
- 利用URL的Hash模式:就是常说的锚点,javascript通过 hashChange事件来监听URL的改变。(IE7及以下版本需要使用轮询)。在地址中以’#'分隔页面。
- 利用HTML5的History模式:它使用URL看起来像普通网站一样,在地址中以’/'分隔页面。但是页面并没有跳转。这种模式需要服务器端支持,服务端在接收到所有的请求后,都指向同一个HTML文件,不然会出现页面错误。
3.VueRouter路由
路由就是根据一个请求路径选中一个组件进行渲染的决策过程。VueRouter路由是Vue官方推出的路由管理器。
- route:表示单个路由。
- routes:表示多个路由的集合。是一个数组,在这个数组中包含了多个route。
- router:译为路由器,是route、routes的管理者。
路由的查找过程是: router --> routes --> route(当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由)
4.VueRouter的组成
- VueRouter类:路由器类,维护的一种路由表,根据路由请求在路由视图中动态渲染选中的组件。
- router-link:路由的链接组件,类似于<a>标签。声明用以提交路由请求的用户接口。
- router-view:路由视图组件,路由出口,负责动态渲染路由选中的组件。
5.VueRouter常用的函数
- createRouter函数:创建路由器
- createWebHashHistory函数:创建Hash模式的路由
- createWebHistory函数:创建History模式路由
//例如: //1.创建路由器 Const router = createRouter({ //2.指定Hash模式或History模式的页面路由 history: createWebHashHistory(), //3.创建路由集合 routes: [ //4.一个个的route // ....... ], })
二、VueRouter的使用
1、安装vue-router
npm install vue-router (前提:先在webstorm创建并配置vue项目)
2、创建路由文件
- 定义路由表:routes,在路由表中包含多个route
- 创建路由器:router,在路由器中指定路由表(routes)以及路由模式(hash/history)
// 引入vue-router import {createRouter, createWebHashHistory, createWebHistory} from "vue-router"; import Home from "../***ponents/Home.vue"; import About from "../***ponents/About.vue"; //定义路由表 const routes = [ { path:'/home', ***ponent: Home, name: 'home' }, { path:'/about', ***ponent: About, name: 'about' } ] //定义路由器 const router = createRouter({ routes, history: createWebHistory() }) //导出路由器 export default router;
3、声明路由请求接口
- 路由链接组件(router-link)为用户提供了提交路由请求的交互接口。使用to属性来声明链接组件的目标路径,当用户点击链接组件时,组件向路由器提交向目标路径的路由请求。
- 在模板中,使用<router-link>标签声明路由链接元素。
- 例如,下面的示例声明了一个目标路径为/about的路由链接:
<router-link to=“/about”>ABOUT</router-link>
注意:上例中的“/about”必须在路由表中出现。
4、声明路由出口
- 路由视图组件(router-view)为路由器($router)提供了所选中组件的渲染出口。
- 在模板中,使用标签<router-view>声明路由视图元素。
- 例如,下面示例在模板中声明了一个路由视图:
<router-view></router-view>
***ponents目录下的Home.vue组件代码段:
<template> <h2>我是home组件</h2> </template> <script> export default { name: "Home" } </script> <style scoped> </style>
***ponents目录下的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 "../***ponents/Home.vue"; import About from "../***ponents/About.vue"; const rs = [ //定义路由表 { path:'/home', ***ponent: Home, name: 'home' }, { path:'/about', ***ponent: 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 './***ponents/HelloWorld.vue' </script> <template> <!--创建路由的链接组件(路由接口)--> <div> <router-link to="/home">Home</router-link> <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.参数名’获取参数。
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 './***ponents/HelloWorld.vue' </script> <template> <!--创建路由的链接组件(路由接口)--> <div> <router-link to="/user/项羽">动态路由---项羽</router-link> <router-link to="/user/刘邦">动态路由---刘邦</router-link> </div> <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" /> <router-view></router-view> </template>
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 "../***ponents/User.vue"; const rs = [ //定义路由表 { path: '/user/:name', ***ponent: User, name:'user' } ] //定义路由器 const router = createRouter({ routes:rs, history: createWebHistory() }) //导出路由器 export default router
效果图:
2.在URL中带查询参数
在URL中带查询参数:/组件名?参数名=参数值;在组件中通过’$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 './***ponents/HelloWorld.vue' </script> <template> <!--创建路由的链接组件(路由接口)--> <div> <router-link to="/library?id=1">图书1</router-link> <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 "../***ponents/Library.vue"; const rs = [ //定义路由表 { path: '/library', ***ponent: 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"> <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文件:
注意:***ponent: ()=>import(‘…/***ponents/Books.vue’)另一种引入组件的写法
import {createRouter, createWebHashHistory, createWebHistory} from "vue-router"; const rs = [ //定义路由表 { path: '/books', name: 'books', ***ponent: ()=>import('../***ponents/Books.vue'), children: [{ path: '/books/book/:id', ***ponent: ()=>import('../***ponents/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 './***ponents/HelloWorld.vue' </script> <template> <!--创建路由的链接组件(路由接口)--> <div> //<router-link to="/home">Home</router-link> // //<router-link to="/about">About</router-link> <router-link :to="{name:'home'}">Home</router-link> <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>
效果图:
六、命名视图
命名视图:给路由视图()一个名称,可以将组件渲染到指定名称的路由视图中。
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.在路由表中,指定***ponents属性的值
例如routers目录下的router.js文件:
{ path: '/books', name: 'books', ***ponent: ()=>import('../***ponents/Books.vue'), children: [{ path: '/books/book/:id', //***ponent: ()=>import('../***ponents/Book.vue') ***ponents:{ test:()=>import('../***ponents/Book.vue') } }] }
因为指定的路由视图是test,所以将会渲染到视图name为test上,也就是第一个 横线的下方,第二个横线的上方。(如果为bookDetail,则在第二条线的下方)
七、导航守卫
1.路由导航的方式
- 标签导航:<router-link to=“url”></router-link>
- 编程式导航: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 '../***ponents/Home.vue'; import Login from '../***ponents/Login.vue'; const rs = [ { path:'/home', name:'home', ***ponent:Home }, { path:'/login', name:'login', ***ponent: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 './***ponents/HelloWorld.vue' import Login from './***ponents/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>
效果图: