> 文章列表 > vue 路由

vue 路由

vue 路由

路由router

注意 $ router全局的 vs $ route当前活跃的

路由核心:改变URL路径,但是页面不进行整体刷新
路由可以理解为指向
路由表,是一个映射表,一个路由就是一组映射关系,
key:value key表示路由,value可以为function或者Component
function为后端路由用来处理后端请求
Component(组件)为前端路由用来展示不同内容

vue Router

安装路由Router并挂载

npm install vue-router@4
可以在任意组件中以 this.$router 的形式访问它,
并且以 this.$route 的形式访问当前路由、import router from './router'
const app =createApp(App)
app.use(router)
app.mount('#app')

导入的Router index文件

import { createRouter, createWebHashHistory } from 'vue-router'
// 1. 定义路由组件.
// 也可以从其他文件导入
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import Disan from '../views/Disan.vue'// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
//路径、子组件名
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/Disan/:id', component: Disan }
]// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
export default router

带参数的动态路由匹配

<template>
<div>用户</div>
</template>
<!--vue2写法 <script>
export default{
mounted(){// $route表示当前活跃的路由对象console.log(this.$route);console.log(this.$route.params.id);}
}
</script> -->
<!-- 组合式API写法 -->
<script setup>
import {useRoute} from 'vue-router'
console.log(useRoute().params.id);
</script>

app组件

<script setup>
// 定义响应式变量,还是需要从vue中引入
import {ref} from 'vue'
// vue3 引入组件不需要注册
import Qwer from './components/Qwer.vue'
//  定义变量,在模板使用不需要暴露出去,模板直接使用
const a=20
console.log(a);
const b=ref(1)
function adds(){b.value++
}
</script><template><div><!-- vue-router是基于路由和组件的,路由是用来设定访问路径,将路径和组件映射起来 --><h1>Hello App!</h1><p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签--><!-- 使用一个自定义组件 router-link 来创建链接,这使得 Vue Router可以在不重新加载页面情况下更改URL,处理URL 的生成以及编码 --><!-- to="路径" -->
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
<router-link to="/Disan/123">Go to Disan</router-link></p><!-- 路由出口。占位符 --><!-- 路由匹配到的组件将渲染在这里 --><router-view></router-view></div></template>

找不到动态参数 路由正则与重复参数

如果动态参数找不到404的话要给一个提示

import News from '../views/News.vue'
// 报错文件
import NotFound from '../views/NotFound.vue'定义一些路由
const routes = [{ // 动态路由的参数一定是数字// 这里注意需要使用两个反斜杠,第一个反斜杠用来转义。所以\\\\d表示匹配任何一个数字字符。path: '/News/:id(\\\\d+)', // 有多个参数 +path: '/News/:id+', // 参数可有可无,参数可以重复叠加path: '/News/:id*', // 参数可有可无path: '/News/:id?', component: News // ?与*区别,?后面不可以有多个参数,*可以},// 报错文件使用正则来表示。匹配任意的
// 404页面
{ path: '/:path(.*)', component: NotFound },
]

嵌套路由(children)

首先把父组件与需要嵌套的子组件引入到index文件。

import { createRouter, createWebHashHistory } from 'vue-router'
import Qiantao from '../views/Qiantao.vue'
import Qiantaoone from '../views/Qiantaoone.vue'
import Qiantaotwo from '../views/Qiantaotwo.vue'
const routes = [{   path: '/Qiantao', component: Qiantao,children:[ //children类似于上面const routes{path: 'Qiantaoone', component: Qiantaoone},  { path: 'Qiantaotwo', component: Qiantaotwo },]

在父组件中写入(子组件已写好ol列表与ul列表)

<template><div><h2>嵌套练习</h2><router-link to="/Qiantao/Qiantaoone">样式一</router-link><router-link to="/Qiantao/Qiantaotwo">样式二</router-link><router-view></router-view>  //占位符输出口
</div>
</template>

编程式导航

通过js来实现跳转页面

$router 相当于全局路由器,可以拿到push,forword ,back,go方法
$route 当前活跃的路由对象
通过$route 来拿到path,params获取参数,query,name
this.$router.push用来跳转页面 。

vue 路由
获取参数 params

<template>
<div><h2>Page编程式</h2><button @click="goPage">跳转页面</button>
</div>
</template>
<script>
export default{
methods:{goPage(){// console.log(this.$router);//    if(123==123){// 第一种方式// this.$router.push('/')// 第二种通过传入对象// this.$router.push({path:"/"})// 带参数// this.$router.push({path:"/Disan/123456"})// params是一个对象传入id// this.$router.push({name:"news",params:{id:123123}})// 带问号 query就是相当于?后面的内容this.$router.push({path:"/about",query:{name:"zhangsan"}})//    }}
}
}
</script>

替换当前位置:

作用类似于router.push,不同点在于导航不会像 history 添加新记录,
router.push({ path:"/home" , replace: true})
相当于 router.replace({ path:"/home" })

// 替换当前位置

    //第一种方式
this.$router.push({path:"/about",query:{name:"zhangsan"},replace:true })//第二种方式this.$router.replace({path:"/about",query:{name:"zhangsan"}})

比如有3个页面,主页,页面1(page),页面2(about)
我进入主页然后进入页面1,点击按钮执行上面代码替换为页面2,
点击浏览器左上角的后退,返回到主页面,而不是页面1.
再次点击浏览器左上角前进,返回到页面2。

横跨历史 (go、forword、back)

模板中写入按钮
<button @click="goBack">后退</button>
绑定一个@click事件,执行下列代码// 前进,传入为正值,后退,传入为负值
methods:{goBack(){// 前进,传入为正值,后退,传入为负值this.$router.go(-2)// this.$router.back() //等于go(-1),但是不可以传参//this.$router.forworf() //等于go(1)}
}

命名路由

除了 path路径 之外,你还可以为任何路由提供 name ,这有以下优点:

index路由文件中

import News from '../views/News.vue'
const routes = [{name:"news",path: '/News/:id*',component: News }

App组件通过path与命名路由

<router-link to="/News/1211">Go to News</router-link>
<router-link v-bind:to="{name:'news',params:{id:911}}">Go to News</router-link>
<router-view></router-view>

命名视图(components)注意+s多个

当我们想要展示多个视图,而不是嵌套展示,就需要命名视图了
index路由中

import ShopTop from '../views/ShopTop.vue'
import ShopMain from '../views/ShopMain.vue'
import ShopFooter from '../views/ShopFooter.vue'
const routes = [{path:'/Shop',components:{default:ShopMain,// 它们与<router-view>上的<name>属性匹配ShopTop:ShopTop,ShopFooter:ShopFooter}}
]

app组件中

	<router-view name="ShopTop"></router-view><router-view></router-view><router-view name="ShopFooter"></router-view>

重定向(redirect)可以路径、命名路由name、方法

例如home页面 path路径为/home 进行跳转,通过重定向可以实现“ / ”达到跳转home页面index.js路由const routes = [
{ path: '/' ,// 重定向redirect:"/home"//命名路由// redirect:{name:'home'}// 方法redirect:(to)=>{console.log(to);return {name:"home"}
},
{ path: '/home',name:"home", component: Home },]

别名(alias)

当我们的path路径过长等,需要一个或多个别名,多个用数据
path: '/Qiantao', // alias:'/father',//起别名alias:["/father","/faqin"],component: Qiantao,http://localhost:5173/#/Qiantaohttp://localhost:5173/#/fatherhttp://localhost:5173/#/fuqin结果是一样的

将props传递给路由组件

index路由import Disan from '../views/Disan.vue'
{ path: '/Disan/:id', component: Disan , props: true },选项式API写法export default{props:['id'],mounted(){console.log(this.id);
组合式API写法(defineProps({ }))<script setup>import {useRoute} from 'vue-router'const props= defineProps({id:String //因为路径为字符串格式。})console.log(props.id);</script>

index路由中需要给每个都要加上props

const router =	[{path:'/Shop/:id',components:{default:ShopMain,// 它们与<router-view>上的<name>属性匹配ShopTop:ShopTop,ShopFooter:ShopFooter},props:{default:true,ShopTop:false,ShopFooter:false}
}]

这个时候ShopMain.vue 组件中就可以接受到id值

<script>
export default{props:["id"],
mounted(){console.log(this.id);
}
}
</script>

另外组件接收的话,结果为空,除非index中props修改为ture进行接收

不同的历史模式(Hash模式、HTML5模式)

1、Hash模式使用createWebHashHistory()创建的
路径上有一个# 叫做哈希字符
2、HTML5 模式用 createWebHistory()创建的
区别:html5需要后端服务器配置好,不然刷新可能会出现404,
哈希字符不会请求后端。
一个有#号 一个没有

路由守卫

 导航守卫主要用于跳转或取消的方式守卫导航,植入路由导航中:全局、单个路由、组件级。有3个参数to 即将要进入的目标from 当前导航正要离开的路由 next:相当于加了一个关卡,需要调用一下next()//直接进to 所指路由next(false) //中断当前路由next('route') //跳转指定路由next('error') //跳转错误路由全局前置路由:

全球守卫(全局守卫)

router.beforeEach((to,from,next)=>{console.log(to);console.log(from);next()//通行证
})

每路守卫(路由独享守卫)

{ path: '/about',component: About,// 每路守卫(路由独享守卫)beforeEnter:(to,from,next)=>{//if判断token值console.log(to);console.log(from);if(123===123){next()}}}

组件内的守卫(进入、更新、离开之前)

有3个守卫 路由进入组件之前,更新之前,离开之前
beforeRouteEnter(){}
beforeRouteUpdate(){}
beforeRouteLeave(){}// 注意在 beforeRouteEnter是拿不到this的因为这是在组件创建之前。
//拿不到实例对象,通过next的回调函数来进行获取export default{
data(){return{age:18}
},
beforeRouteEnter(to,from,next){console.log("路由进入组件之前");console.log(to);console.log(from);// console.log(age);不能执行next((vm)=>{console.log(vm.age);})
},
beforeRouteUpdate(){console.log("路由更新组件之前");},
beforeRouteLeave(){console.log("路由离开组件之前");}
}

路由懒加载(返回的是一个promise组件函数)

	在项目中一次引入过多,JavaScript包变的特别大.影响页面加载。让静态导入变成动态导入  需要用到在加载。静态引入	import Home from '../views/Home.vue'动态引入	const home = ()=>import('../views/Home.vue'){ path: '/home',name:"home", component: home}

如果 命名视图的话
想要展示多个视图

// import ShopTop from '../views/ShopTop.vue'
// import ShopMain from '../views/ShopMain.vue'
// import ShopFooter from '../views/ShopFooter.vue'
改为动态
const Top = ()=>import('../views/ShopTop.vue')
const Main = ()=>import('../views/ShopMain.vue')
const Footer = ()=>import('../views/ShopFooter.vue')const router =	{path:'/Shop/:id',components:{default:Main,// 它们与<router-view>上的<name>属性匹配ShopTop:Top,ShopFooter:Footer}]