Vue-router
路由核心:改变URL,但是页面不进行整体刷新。路由理解为指向的意思,其中有很重要的一个关键就是路由表。
路由表,是一个映射表,一个路由就是一组映射关系,key:value
key用来表示路由,value可以是function
或者是Component
(组件)。
后端路由value为function用来处理客户端的请求,前端路由value为Component用来展示内容。
vue-router是基于路由和组件的,路由是用来设定访问路径,将路径和组件映射起来
npm install vue-router@4
项目结构
JavaScript
在src下创建router文件夹,新建index.js
从官网的router->基础->入门->JavaScript下复制1-4点
// 1. 定义路由组件.
// 也可以从其他文件导入
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = VueRouter.createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: VueRouter.createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
但还不能进行能够使用要稍加更改
在src下创建views文件,存放路由组件,新建Home.vue
和About.vue
分别写上
<template>
<div>home</div>
</template>
<template>
<div>about</div>
</template>
在index.js
修改步骤1
// 1.从其他文件导入
import Home from '../views/Home.vue'
import About from '../views/About.vue'
步骤2中如果导入名字不同,需要修改component: Home
步骤3和4中可以不使用VueRouter.
来获得createRouter
。先在index最开始引入
import {createRouter,createWebHashHistory} from 'vue-router'
然后去掉VueRouter.
const router = createRouter({
history: createWebHashHistory(),
routes,
})
步骤4 有history
模式也有hash
模式,以后会讲解。
最后在结尾导出
export default router
在main.js中引入再使用
注意:这里是有先后顺序的app中用了路由,所以router要在前使用
//此处/index.js可省略会默认找到
import router from './router/index.js'
const app = createApp(App)
app.use(router)
app.mount('#app')
HTML
router-link
用自定义组件 router-link
代替a标签,最后渲染出来是a标签。达到可以在不重新加载页面的情况下更改 URL的目的,to填index.js
步骤2中routes的path
<router-link to="/">Go to Home</router-link>
router-view
路由出口,占位符。路由匹配到的组件将渲染在这里
<router-view></router-view>
动态路由匹配
相应路由参数变化
比如在views下有一个User.vue
组件,我希望不同的用户都能以这个组件为基础填上不同的信息。
在App.vue
中
<router-link to="/use/123">Go to User</router-link>
此时我想要拿到数据123,需要
在index.js
中
路径字段以冒号开始/user/:id
,id的值将会在每个组件中以this.$router.params
的形式暴露出params是参数的意思。但组合式API无法使用,因为setup中没有this。
注:动态路由无论id是什么都会进入user页面
const routes = [
...
{ path: '/user/:id', component: User },
]
Vue2做法
在User.vue
中
<script>
export default{
mounted(){
console.log(this.$route.params.id)
}
}
</script>
vue3做法
在User.vue
中
从vue-router
引入useRoute()
函数,再然后通过params访问id等参数。
<script setup>
import { useRoute } from 'vue-router';
console.log(useRoute().params.id);
</script>
404页面
当输入不匹配的路由的时候我希望返回404页面
在veiws
文件夹下新建NotFound.vue
。再在indes.js
中引入,定义路由的时候使用正则的方式。
/:path(.*)
表示匹配任意页面,但是如果前面出现了匹配成功的就不会走到正则这里。
const routes = [
...
{ path: '/:path(.*)', component: NotFound },
]
路由正则
?表示0个或1个 +号1个或多个 *号0个或多个
新建News.vue
并且在index中导入
需求:动态路由的参数一定为数字。双杠表示匹配,d表示数字,+表示后面都为数字。[0-9]*也可。
const routes = [
...
{ path: "/news/:id(\\d+)", component:News}
]
需求:有多个参数也同样可以匹配,比如/news/123/aaa
。+表示接受多个参数。
{
path: "/news/:id+",
component: News
},
需求:参数可有可无,*和?表示参数可有可无。但是两者不同的点是问号不接受多个参数,比如/news/123/aaa
。
{
//path: "/news/:id*",
path: "/news/:id?",
component: News
},
嵌套路由
某些页面是多层组件嵌套的,子路由可以通过数据判断进哪一个。
在views中新建Parent.vue
Styleone.vue
Styleweo.vue
index.js
中
children:
定义子路由,和routes
一样以数组的形式定义,只是path前不需要加斜杠
const routes = [
...
{
path: '/parent',
component: Parent,
children: [
{ path: "styleone", component: StyleOne },
{ path: "styleone", component: StyleTwo },
]
},
]
Parent.vue
中
<div>
<h2>父组件Parent</h2>
<RouterLink to="/parent/styleone">样式1</RouterLink>
<RouterLink to="/parent/styletwo">样式2</RouterLink>
<RouterView></RouterView>
</div>
JS转跳页面
除了RouterLink
的转跳方法,比如登陆的时候我需要验证过后才允许转跳。
在 Vue 实例中,你可以通过 $router(一个对象)
访问路由实例。因而可以可以调用 this.$router.push
、forword(返回)、go方法。
$route
则是当前活跃的路由对象,在这里面就可以拿到path、params、query、name等。
在views中新建Page.vue
<button @click="goPage">跳转页面</button>
export default{
methods:{
goPage:function(){
if (1 == 2)
this.$router.push('/')
}
}
}
传入对象
this.$router.push({path:"/"})
带参数
this.$router.push({path:"/user/123456"})
或者利用name和params:
分开写
index.js
中
const routes = [
{name: "news",path: "/news/:id?",component: News},]
Page.vue
中
this.$router.push({ name: "news", params: { id: 123 } })
带问号
通过query:
接受带问号的
this.$router.push({ path: "/about", query: { name: "zhangsan" } })
点击跳转网址显示为
http://localhost:5173/#/about?name=zhangsan
此时在About.vue
中即可获取query里面内容,vue3中引入userRouter
export default{
mounted(){
console.log(this.$route.query.name)
}
}
前进后退
替换当前位置
如果在一次访问ABC页面之后,B页面不想第二次展示,那么需要在历史纪录中,用C直接覆盖替换B。可在传递给 router.push
中增加一个属性 replace: true
this.$router.push({ path: "/about", query: { name: "zhangsan" } ,replace:true})
或者用replace方法替换push
this.$router.replace({ path: "/about", query: { name: "zhangsan" } })
横跨历史
在历史堆栈中前进or后退多少步
在About.vue
中
vue2写法
$router.go()
方法参数正前进,负后退
<button @click="goBack()">后退</button>
export default{
methods:{
goBack(){
this.$router.go(-1)
}
}
}
vue3中引入userRouter后
router.go(-1)
命名路由
除了 path
,给路由起一个名字 name
。下优点:
- 没有硬编码的 URL
params
的自动编码/解码。- 防止你在 url 中出现打字错误。
- 绕过路径排序(如显示一个)
在App.vue
中
想要让to识别对象,绑定一下变成动态的
<router-link :to="{name:'news',params:{id:456}}">Go to News</router-link>
命名视图
在项目结构上components一般用于存放独立或者公共的组件,在views实际开发中通常会再根据页面新建文件夹,比如一个Home放着该页面下的组件
现在需求访问单个路径显示多个视图,同级展示。如访问/shop同时显示三个组件。(但似乎这种方式用的少)
新建ShopTop.vue
ShopMain.vue
ShopFooter.vue
index.js
中引入
小名:组件。default:
是必要的,提供默认显示。ShopTop:ShopTop
可属缩写。
{
path:"/shop",
components:{
default:ShopMain,
ShopTop,
ShopFooter:ShopFooter,
}
},
App.vue
中
<router-view name="ShopTop"></router-view>
<router-view></router-view>
<router-view name="ShopFooter"></router-view>
重定向和别名
redirect:
当我希望访问/
和/home
链接都是home页面,可以在定义路由中使用redirect:
重定向
const routes = [
{ path: '/',
redirect:'/home'
},
{ path: '/home', component: Home },
]
命名路由
除了路径还可已使用name
const routes = [
{ path: '/',
redirect: {name:"home"}
},
{ path: '/home', name: "home", component: Home },
]
返回方法
这种做法可以在函数里写上判断,比如访问/:123
参数to
参会包含id=123的数据(但是不推荐),返回值可以是path
也可以是name
。
const routes = [
{ path: '/:id',
redirect:(to)=>{
console.log(to)
return {path: '/home'}
}
},
]
alias:
起别名,数组形式可以
{path: '/parent',alias: '/father',...},
alias: ['/father', '/fuqin']
路由组件传参
使用$route
和 useRoute()
从URL上获得参数,会导致和路由紧密耦合,可以通过 props
配置来解除这种行为。
布尔模式
在index.js
中
设置 props:true
const routes = [
{
path: '/user/:id',
component: User,
props:true,
},
]
在User.vue
中
vue2做法,此时this.id完美替代上面一句$route
<script>
export default {//路由组件传参vue2用法
props: ['id'],
mounted() {
//console.log(this.$route.params.id);
console.log(this.id);
}
}
</script>
vue3做法,使用defineProps()
,参数必为String类型
<script setup>
//import { useRoute } from 'vue-router';
//console.log(useRoute().params.id);
const props = defineProps({
id: String
})
console.log(props.id)
</script>
命名视图
在index.js
中
以数组的形式设置 props:
{
path: "/shop/:id",
components: {
default: ShopMain,
ShopTop,
ShopFooter,
},
props:{default:true,ShopFooter:false,ShopTop:false}
},
vue2做法,同布尔模式
vue3做法,同布尔模式
对象模式和函数模式具体见文档
历史记录模式
Hash模式
hash 模式是用 createWebHashHistory()
创建。标准是 URL 之前使用了一个哈希字符(#
)
http://localhost:8888/#/shop/123
const router = createRouter({
history: createWebHashHistory(),
routes,
})
export default router
HTML5模式
用 createWebHistory()
创建 HTML5 模式,推荐使用这个模式,但是后端没配好就容易404
import {...,createWebHistory} from 'vue-router'
...
const router = createRouter({
history:createWebHistory(),
routes,
})
export default router
即可访问
http://localhost:8888/home
导航守卫
通过跳转或取消的方式守卫导航。方式:全局的,单个路由独享的,或者组件级的。
全局前置守卫
用的较多,又称全全局守卫
使用 router.beforeEach
注册一个全局前置守卫,进入每一个路由组件的时候都会触发填入的回调函数。
回调函数参数1to
去哪里,参数2from
从哪来。
index.js
中
router.beforeEach((to, from) => {
console.log(to)
console.log(from)
})
参数3next
导航守卫,当添加这个参数的时候,只有成功next()
才会跳转。
router.beforeEach((to, from, next) => {
console.log(to)
console.log(from)
next()//通行证
})
局部路由守卫
又称每路守卫,作用于单个路由,使用beforEnter:
参数还是to、form、next
index.js
中
{
path: '/about',
component: About,
//每路守卫,独享的守卫
beforeEnter: (to, from, next) => {
console.log(to)
console.log(from)
if (1 == 1) {
next()
}
}
},
组件内的守卫
类似生命周期钩子,可以为路由组件添加以下配置:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
在News.vue
中
<script>
export default {
beforeRouteEnter() {
console.log('路由进入组件之前');
},
beforeRouteUpdate() {
console.log('路由更新组件之前');
},
beforeRouteLeave() {
console.log('路由离开组件之前');
},
}
</script>
同样也有参数to、form、next,因为beforeRouteEnter
是还拿不到实例对象(另外两个可以),所以需要next写回调函数。
vm
是自己取名的参数,相当于外面的this
export default {
data() {
return {
age: 18,
};
},
beforeRouteEnter(to, from, next) {
next((vm)=>{
console.log(vm.age)
})
},
}
路由懒加载
如果一次性要在index.js
中引入非常多的组件,会导致加载很慢。
//静态导入
import Home from '../views/Home.vue'
...
路由懒加载,用到时候再加载
{
path: '/home',
name: "home",
component:()=>import('../views/Home.vue')
},
但是更建议在抽取出来更好管理
const Home = () => import('../views/Home.vue')
const routes = [
{
path: '/home',
name: "home",
//component: Home
component: Home
},
]
标签:vue,--,Vue,path,组件,router,id,路由
From: https://www.cnblogs.com/TimothyWen/p/16986652.html