关于vue路由 这是关于前端的知识 我大致就理解为其为跳转规则
html中跳转想一下 jsp跳转 或者 直接a标签跳转
这个为人家规范的跳转
这是vscode用到一些小插件
{图标和idea键盘操作 挺不错的}
当然你需要vue插件 否则无法识别vue
还有就是node.js的安装就不说了
首先分为前后端路由
我们主要介绍前端路由
其整个过程发生在浏览器端
- Hash模式 url中带有#
- HTML5模式 就太熟悉了没有# 直接为路径
不是吧不是吧 现在还能分不清URL和URI URI是唯一标识
两者在运用中对应的函数用于指定路由的工作模式
- createWebHashHistory()函数 即Hash模式
- createWebHistory()函数 HTML5模式
后面通过例子还会介绍
用它那是不是就得有它啊 首先就是Vue Router的安装 哈哈这里有个坑 一会介绍
首先进入你的项目路径下
当然vue Router有很多版本 安装方式也很多 4对应着vue3版本
使用一下命令的时候 你要确保你电脑上有yarn依赖的东西
yarn add vue-router@4 --save
安装后检查下啊
哦哦哦再给个小建议 关于注释的
https://cloud.tencent.com/developer/article/2095044 注释生效
那现在来看看如何使用
举个例子 既然要跳转就起码有两个以上的页面
先说两个基础的 一个Home页面 和一个 About页面
创建就跳过了 就是简单显示个东西
为了显示在App.vue中显示
使用 scoped 后,父组件的样式将不会渗透到子组件中 解决样式冲突
<template>
<div class="app-container">
<h1>App根组件</h1>
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<hr>
<router-view></router-view>
</div>
</template>
<script setup>
这个为监听器
import{watch} from 'vue'
import { useRoute } from 'vue-router';
useRoute()函数用于获取路由参数 为了后面监听
const route=useRoute()
watch(()=>route.path,path=>{
console.log(path);
})
</script>
<style scoped>
.app-container {
text-align: center;
font-size: 16px;
}
.app-container a {
padding: 10px;
color: #000;
}
.app-container a.router-link-active {
color: #fff;
background-color: #000;
}
</style>
使用 scoped 后,父组件的样式将不会渗透到子组件中 解决样式冲突
<router-link to="/home">首页</router-link>
<router-view></router-view>
这个就是核心
再插个话题 关于箭头函数 参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arrow_functions
然后就需要配置相关的跳转 在router.js中配置
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
这里有两种跳转方式 第一种不写了 因为大部分为第二种懒加载的方式
routes: [
主页面 路由重定向
{ path: '/', redirect: '/home' },
{ path: '/home', component: () => import('./components/路由/Home.vue') },
{
path: '/about', component: () => import('./components/路由/About.vue')
]
})
导出路由实例对象
export default router
首先导入的模块依赖 这里就有个坑
哈哈后面使用的也是这个 是useRouter不是Route
参考 https://blog.csdn.net/m54584mnkj/article/details/122853884 useRoute()和useRouter()区别
在main.js中导入并挂载路由模块
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
导入路由模块
import router from './router.js'
const app = createApp(App);
挂载路由模块
app.use(router);
app.mount('#app');
这里也有个坑
createApp(App).mount('#app')
createApp(App).use(router) 错误只能创建一个vue应用实例
这是我之前写的 错误错误
效果先不看很简单 对比下面看个综合的
嵌套路由 需要用到children属性定义子路由匹配规则
我们向About中套两个新页面
例如
<template>
<div>table1组件</div>
</template>
<style scoped>
div{
text-align: left;
background-color: antiquewhite;
}
</style>
<template>
<div class="about-container">
<h3>About组件</h3>
主要多了这两个 类似App.vue中显示Home和About一样
<router-link to="/about/one">table1</router-link>
<router-link to="/about/two">table2</router-link>
<hr>
<router-view></router-view>
</div>
</template>
<style scoped>
.about-container {
min-height: 150px;
background-color: #f2f2f2;
padding: 15px;
}
.about-container a {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px 10px;
color: #000;
margin: 0 5px;
}
.about-container a.router-link-active {
color: #000;
background-color: #deebf6;
}
</style>
路径写完了需要配置下
在router.js中
{
path: '/about', component: () => import('./components/路由/About.vue'),
children: [
{ path: 'one', component: () => import('./components/路由/Table1.vue') },
{ path: 'two', component: () => import('./components/路由/Table2.vue') }
]
},
动态路由
路径上带有参数值
在App.vue中再来个跳转
<router-link to="/movie">电影</router-link>
<template>
<div class="about-container">
<h3>Movies组件</h3>
<router-link to="/movie/1">电影1</router-link>
<router-link to="/movie/2">电影2</router-link>
<hr>
<router-view></router-view>
</div>
</template>
<style scoped>
.about-container {
min-height: 150px;
background-color: #f2f2f2;
padding: 15px;
}
.about-container a {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px 10px;
color: #000;
margin: 0 5px;
}
.about-container a.router-link-active {
color: #000;
background-color: #deebf6;
}
</style>
这次不用单独去写两个电影 1 2 页面 而是写一个页面
关于获取参数值
两种方式
- {{ $route.params.id }}
- props获取路由参数值
<template>
<!-- <p>电影{{ $route.params.id }}页面</p> -->
<p>电影{{ id }}页面</p>
<br>
</template>
<script setup>
const props=defineProps({
id:String
})
</script>
别忘记在router.js中配置
记得开启props传参
{
path: '/movie',
component: () => import('./components/路由/Movies.vue'),
children: [
{ path: ':id', name: 'MoviesCCC', component: () => import('./components/路由/MoviesCCC.vue'), props: true }
]
}
:id 属性绑定语法
这里也有个坑就是我将
{ path: ':id', component: () => import('./components/路由/MoviesCCC.vue'), props: true }
写在了外面
.vue-router.js?v=8a787c14:954 Uncaught Error: Route paths should start with a "/": ":id" should be "/:id".
:id 要加/ (命名路由)
那时候要加上/
命名路由
使用name属性定义路由名称
name属性值不能重复 是唯一的
动态绑定to属性
要使用v-bind指令进行绑定
假如在Home页面跳转到电影页面并且携带参数
这里有个小坑 注意下 就是"" 里面要是''单引号
<router-link :to="{ name: 'MoviesCCC', params: { id: 2 } }">跳转到MoviesCCC2</router-link>
要在router.js中修改
加上name属性
{ path: ':id', name: 'MoviesCCC', component: () => import('./components/路由/MoviesCCC.vue'), props: true }
编程式导航
两种导航方式
- 声明式导航
<router-link></router-link>
-
编程式导航
先使用useRouter()函数获取全局路由实例 常用方法push() go() replace() -
push()
向历史记录添加一个新的记录 以编程方式导航到一个新的URL 若在参数对象中提供了path则params会被忽略 需要使用name属性或者手动拼接带有参数的path
例如在Home中添加
a标签默认有自己的href属性 触发a标签后他会自动跳转对应的链接地址或执行的函数
此处为了嵌套 避免调整样式所以引用了a标签来处理 但又为了避免a标签的属性限制
因此引用了@click.prevent函数阻隔默认的操作
<a href="#" @click.prevent="pushgo(1)">跳转到MoviesCCC1</a>
<script setup>
import { useRouter } from 'vue-router';
先使用useRouter()函数获取全局路由实例
const router = useRouter()
const pushgo = go_id => {
router.push({
name: 'MoviesCCC',
params: { id: go_id }
})
}
</script>
- replace()
与push()方法类似 区别在于后者不会向历史记录添加新的记录而是替换
- go()
用于实现前进后退效果 类似js中window.history.go() 相应的地址栏也会改变
go(1) 前进一条 go(-1)后退一条
具体看下例子
<button @click="goback">后退</button>
import { useRouter } from 'vue-router';
const router=useRouter()
const goback=()=>{
router.go(-1)
}
导航守卫
可以理解为拦截器吧 就是没有输入账号密码跳转登录页面
- 全局导航守卫 常用
- 导航独享守卫 单个路由
- 组件导航守卫
再写个login页面
<template>
<h1>登录页面</h1>
</template>
然后再router.js中配置 要在导出路由实例之前
//全局导航守卫
三个参数 to目标路由对象 from当前要离开的路由对象
如果不接受next()函数 则默认运行访问任何一个路由 若调用 则需要调用next()函数
next()执行下一个钩子函数
next(false)强制停留在当前页面
next('/')跳转到其他地址
router.beforeEach((to, from, next) => {
let flag = false
if (to.name == 'MoviesCCC') {
if (flag) {
next()
} else {
next({ name: 'Login' })
}
} else {
next()
}
}
)
最后来看下效果