入门 | Vue Router (vuejs.org)

安装

1
yarn add vue-router@next ##@next表示安装最新版本

vue3.0默认是router4+的版本而vue2使用的是3的版本

查看安装的router包

1
2
yarn list | findstr router	##windos用这种即可
yarn list | grep router ##windos上好像并不支持grep

路由初始化

src/router/index.js文件内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 路由的列表
import {createRouter, createWebHistory} from "vue-router";
import Home from "@/View/Home.vue";
// import Home from '../View/Home.vue'
// import Register_page from "@/View/Register.vue";

export default createRouter({

history: createWebHistory(),//路由的模式 带不带##号
// history,指定路由模式,此处使用的是history模式 vue2中history命名为mode
// createWebHistory history模式 ==>https:http://localhost:8080/
// createMemoryHistory 带缓存的history模式 ==>https:http://localhost:8080/login
// createWebHashHistory hash模式 ==>https:http://localhost:8080/##/login

routes: [
// {
// path: "url地址",
// component:组件对象
// name:"路由别名"
// },
{
path: "/", //组件的访问路径
component: Home, //不能加引号,直接填写对象即可
name: "Home" //路由别名,按Django开发的惯性来看,应该是可以用来反解析路由名
}, {
path: "/register",
// component: Register_page,
component: () => import(/* webpackChunkName: "Register_page" */ '../View/Register.vue'),
name: "Register"
},
]
}
);

App.vue,代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<router-view></router-view>
</template>


<style>
##app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: ##2c3e50;
margin-top: 60px;
}

页面跳转

测试

Menu.vue中进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
组件标签跳转[本质上还是js跳转]
<router-link to="/">Home</router-link>
|
<router-link to="/register">Register</router-link>

js代码跳转
<template>
<button @click.prevent="goto('/')">主页</button>
<button @click.prevent="goto('/register')">注册</button>
</template>
<script>
const Menu = {
name: "Menu",
methods: {
goto(url){
this.$router.push(url); //跳转到指定的url地址对应的页面中
this.$router.back(); //返回上一个页面
this.$router.go(1); //跳转到指定的n个页面,正数表示前进,负数表示后退
this.$router.forward(); //前进下一个
}
}
}
export default Menu;
</script>
html原生href跳转
<p><a href="/">html-Home</a></p>
<p><a href="/register">html-Register</a></p>

tag

1
<router-link class="col02" tag="li" :to="'/goods/'+sku.id"><img :src="sku.default_image_url"></router-link>

vue-router 3.1.x 以上版本 也是建议使用v-slot处理 原来的tag形式浏览器中没有效果

1
2
3
<router-link :to="'/goods/'+sku.id" custom v-slot="{ navigate }">
<li @click="navigate" @keypress.enter="navigate" role="link" class="col02"><img :src="sku.default_image_url"></li>
</router-link>

不同页面的参数传递

你可以在同一个路由设置有多个参数,它们将会映射到$route.params相应的字段。列如

匹配模式 匹配路径 $route.params
/users/:username /user/eduardo { username : ‘eduardo’ }
/users/:username/posts/:postId /user/eduardo/post/123 {username:’eduardo’,postId:’123’}

除了$route.params之外,$route对象还公开了其他信息,如$route.query(如果URL存在参数)、$route.hash等

Menu.vue

1
2
3
4
5
6
7
8
9
10
11
<template>
<nav>
<router-link to="/">Home</router-link>
|
<router-link to="/register">Register</router-link>
|
<router-link to="/goods">Goods</router-link>
|
<router-link to="/list">List</router-link>
</nav>
</template>

发送和接受查询字符串参数

Goods.vue

数据获取部分均在这一个页面不多写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<template>
<h1>Goods页面</h1>
<p>{{goods_id_query}}号商品的详细信息-query</p>
<p>{{goods_id_params}}号商品的详细信息-params{{cat}}</p>
<nav>
<router-link to="/">Home</router-link>
|
<router-link to="/register">Register</router-link>
|
<router-link to="/goods">Goods</router-link>
|
<router-link to="/list">List</router-link>
</nav>
</template>

<script>
export default {
name: 'GoodsPage',
data(){
return{
goods_id_query:0,
goods_id_params:Number,
cat:Number
}
},
created() {
//接受地址栏的查询字符串
//router用于跳转,router由于获取url的查询参数
this.goods_id_query=this.$route.query.id//id就是查询参数,这一点和express很相
console.log(this.$route.query.cat);
//接受路由参数
this.goods_id_params=this.$route.params.id;
this.cat=this.$route.params.cat;
}
}
</script>

List.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<h1>List页面</h1>
<nav>
<router-link to="/">Home</router-link>
|
<router-link to="/register">Register</router-link>
|
<router-link to="/goods">Goods</router-link>
|
<router-link to="/list">List</router-link>
</nav>
<ul>
<li><router-link to="/goods?id=1">1号商品</router-link></li>
<li><router-link to="/goods?id=5">5号商品</router-link></li>
<li><router-link to="/goods?id=14&cat=7">14号商品</router-link></li>
</ul>
<br>

</template>

<script>
export default {
name:'ListPage',
}
</script>

发送和接受路由参数

Goods.vue

1
如上

List.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<h1>List页面</h1>
<nav>
<router-link to="/">Home</router-link>
|
<router-link to="/register">Register</router-link>
|
<router-link to="/goods">Goods</router-link>
|
<router-link to="/list">List</router-link>
</nav>
<ul>
<li><router-link to="/goods/1">商品1</router-link></li>
<li><router-link to="/goods/5">商品5</router-link></li>
<li><router-link to="/goods/14/7">商品14幸运7</router-link></li>
</ul>
</template>

<script>
export default {
name:'ListPage',
}
</script>

命名路由(反向解析name)

命名路由 | Vue Router (vuejs.org)

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

  • 没有硬编码的 URL
  • params 的自动编码/解码。
  • 防止你在 url 中出现打字错误。
  • 绕过路径排序(如显示一个)
1
2
3
4
5
6
7
const routes = [
{
path: '/user/:username',
name: 'user',
component: User,
},
]

要链接到一个命名的路由,可以向 router-link 组件的 to 属性传递一个对象:

1
2
3
<router-link :to="{ name: 'user', params: { username: 'erina' }}">
User
</router-link>

这跟代码调用 router.push() 是一回事:

1
router.push({ name: 'user', params: { username: 'erina' } })

在这两种情况下,路由将导航到路径 /user/erina

完整的例子在这里.

嵌套路由

嵌套路由是vue-router提供给开发者应用在同一个页面组件下切换不同自组建的时候用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
routes: [
{
path: "/user",//动态路由,设置路由的一部分作为参数,写法必须是 :参数名
component: UserSpace,
children:[
{
path:'friend',
component:UserFriend
}, {
path:'order',
component:UserOrder
},
]
},
]

views/UserSpace.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<template>
<h1>用户公共代码[页面头部]</h1>
<Menu></Menu>
<nav v-if="$route.path==='/user'"><a>当前时间:{{ currentTime }}欢迎回来:阳光</a></nav>
<nav>
<router-link to="/user">个人主页</router-link>
|
<router-link to="/user/friend">好友列表</router-link>
|
<router-link to="/user/order">我的订单</router-link>
</nav>
<router-view></router-view>
</template>
<script>
import Menu from "@/components/Menu.vue";

export default {
name: 'UserSpace',
data() {
return {
currentTime: Date
}
},
methods: {
getCurrentTime() {
const data = new Date();
const hours = data.getHours();
const minutes = data.getMinutes()<10 ? '0'+data.getMinutes() : data.getMinutes();
const seconds = data.getSeconds()<10 ? '0'+data.getSeconds() : data.getSeconds();
this.currentTime = `${hours}:${minutes}:${seconds}`
}
},
mounted() {
this.getCurrentTime();//进入页面调用该方法获取当前时间
clearInterval(myTimeDisplay );//销毁之前定时器
var myTimeDisplay = setInterval(() => {
this.getCurrentTime(); //每秒更新一次时间
}, 1000);
},
components:{
Menu,
}
}
</script>

编写这样一段代码,实现子路由嵌套父路由的组件和url,并且判断在父路由则显示用户信息和当前时间

(http://127.0.0.1:8080/user)

(http://127.0.0.1:8080/user/friend)

src/views/UserOrder.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<h2>Order</h2>
<ul>
<li>上课</li>
<li>上课</li>
<li>上课</li>
<li>上课</li>
<li>上课</li>
</ul>
</template>

<script setup>//setup-vue3的语法糖
</script>

src/views/UserFriend

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<h2>Friend</h2>
<ul>
<li>小红</li>
<li>小白</li>
<li>小绿</li>
<li>小紫</li>
</ul>
</template>

<script setup>//setup-vue3的语法糖
</script>

路由守卫

导航守卫 | Vue Router (vuejs.org)

路由守卫:也叫导航守卫,功能作用类似于上面的axios的拦截器。我们可以基于导航守卫编写一些在页面跳转过程中需要编写的公共代码,例如:权限的验证,页面的公共初始化,页面跳转之前的一些公共逻辑。

前置守卫

在前置路由打印对应的方法信息

1
2
3
4
5
6
7
8
9
10
11
router.beforeEach((to, from, next) => {
console.log(to) //下一个页面的路由对象
console.log(from) //当前页面的路由对象
console.log(next) //
console.log(next()) //执行next()就会往下一个页面跳转
return next()

// console.log(to) //下一个页面的路由对象
// console.log(to.name) //to.name获取下一个路由定义的别名即name
// console.log(to.query) //下一个页面的路由的查询参数 为键值对
// console.log(to.query.id) //下一个页面的路由的查询参数的id键的值 为值
1
2
3
4
5
router.beforeEach((to, from, next) => {
console.log(to) //下一个页面的路由对象
console.log(to.name) //to.name获取下一个路由定义的别名即name
console.log(to.query) //下一个页面的路由的查询参数 为键值对
console.log(to.query.id) //下一个页面的路由的查询参数的id键的值 为值

前置路由拦截用户的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 路由的列表
import {createRouter, createWebHistory} from "vue-router";
import Home from "@/views/Home.vue";
import Goods from "@/views/Goods.vue";
import List from "@/views/List.vue";
import UserSpace from "@/views/UserSpace.vue";
import UserFriend from "@/views/UserFriend.vue";
import UserOrder from "@/views/UserOrder.vue";

const routes = [
//省略
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),//路由的模式 带不带##号
routes
})
//导航首位
//前置守卫,在页面跳转之前需要完成的判断逻辑,公共代码
router.beforeEach((to, from, next) => {
// if ((to.path != "/") && to.path != '/login')
if ((to.name != "Home") && to.path != 'Login'){
if (to.query.user=='小明'){
next();
}else {
next({name:"Home"})
// next({name:"/"})
}
}

else next()
})
export default router


(http://127.0.0.1:8080/user?user=小明)不这样填写内容无非正常访问user页面,或者只能访问登陆和主页面

后置首位

1
2
3
4
router.afterEach((to, from, failure) => {
// if (!failure) sendToAnalytics(to.fullPath)
if (!failure) console.log('对不起你没有权限进入')
})

(路由)独享守卫

1
2
3
4
5
6
7
8
9
10
11
const routes = [
{
path: "/goods/:id",//动态路由,设置路由的一部分作为参数,写法必须是 :参数名
component: Goods,
beforeEnter: (to, from) => {
// reject the navigation
console.log(to);
console.log(from);
return true
},
]

问题

vue-router能不能根据当前访问的路由修改对应的组件,指在router的配置文件index.js实施

大致意识未动态路由匹配动态路径,因为我想后匹配到端渲染的SSR静态模板文件,省去一部分的渲染功夫

解决思路

一、直接在路由配置中进行动态导入路(失败,可跳过)

1
2
3
4
5
6
{
path: '/user/:id',
// component: User
component: () => import((`@/views/User${route.params.id}.vue`)),

}

为定义?那我就拿出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const User = (to, from, next) => {
// 可以访问到 route 对象
// const id = to.params.id
const id = to.params.id
return import(`../views/User${id}.vue`)
}
...

{
path: '/user/:id',
component: User
// component: () => import((`@/views/User${route.params.id}.vue`)),

}

这种根本就四不像,像是路由守卫(导航守卫),又没有对应的方法和实例调用

总而言之在router和组件的script之外没有办法拿到router,使用了useRouter不知道能不能行,反正我当初在试了半天也不行

那使用导航守卫吧

二、使用前置守卫进行拦截然后更改成对应的组件

1.直接替换组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import {createRouter, createWebHistory} from "vue-router";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/user/:id',
component: User
}
]
})
router.beforeEach( (to, from, next) => {
console.log(to.params)
console.log(to.query)
console.log(from.params)
console.log(from.query)
//1.直接替换组件:
to.matched[0].components.default = User2
next();
})
export default router

2.动态导入组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import {createRouter, createWebHistory} from "vue-router";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/user/:id',
component: User
}
]
})
router.beforeEach( async (to, from, next) => {
console.log(to.params)
console.log(to.query)
console.log(from.params)
console.log(from.query)
const dynamic_component =await import(`../views/User${to.params.id}.vue`)
//2.动态导入组件:
to.matched[0].components.default = dynamic_component.default
next();
})
export default router

三、vue的vue-loader(vite默认携带)可以分离组件的template、script、style,通过src导入那么能不能在template初始化之前修改src的属性(失败)

假如使用这一个方法组件就可以固定动态改变的就是页面内容,上面的方法反之,页面内容不会动态改变


本破站由 @BXZDYG 使用 Stellar 主题创建。
本博客部分素材来源于网络,如有侵权请联系1476341845@qq.com删除
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本"页面"访问 次 | 👀总访问 次 | 总访客
全部都是博主用心学编写的啊!不是ai啊 只要保留原作者姓名并在基于原作创作的新作品适用同类型的许可协议,即可基于非商业目的对原作重新编排、改编或者再创作。