通过vue.js我们已经创建了应用,接下来要做的就是将我们的组件映射到路由上去。vue-router能让我们在不完全刷新页面的情况下,根据url的指示,对组件进行展示
基础使用
1.下载安装
npm install vue-router@4
yarn add vue-router@4
2.将组件映射到路由上的基本操作
在src文件夹下创建router文件夹,创建index.js,配置路由参数 一共分为五步 导入需要的模块
import {
createRouter,
createWebHashHistory,
createWebHistory,
} from "vue-router";
1.创建路由组件,或导入路由组件
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
//或静态导入
import User from "../views/User.vue";
// 路由懒加载,在需要的时候才导入,使用关键字About代替路径
const About = () => import("../views/About.vue");
2.定义路由表,每个组件都映射到一个路由
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
3.创建路由实例,并传递 routes 配置
const router = createRouter({
// 4. 内部提供了 history 模式的实现。
// 使用 hash 模式,有# ,不会向服务器发送数据
// history: createWebHashHistory(),
//HTML5模式
history: createWebHistory(),
routes, // `routes: routes` 的缩写
});
export default router;
4.在路由实例内部配置history内部配置 history 模式
5.在main.js里面导入router,并将router实例挂载到跟实例上
import router from './router'
createApp(App).use(router).use(store).mount('#app')//严格按照顺序来
HTML展示
<div id="app">
<p>
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<router-view></router-view>
</div>
router-view展示与url相对应的标签,可以把他放在任何地方,来适应你的布局
router-link 使用这个组件来创建导航链接,to指向路由路径,既路由表中path后面的参数。这个标签能使得不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。
`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签
路由模式
动态路由匹配
对于样式一样,但是数据不一样的情况,例如详情页,那么页面如何加载呢?路由要如何匹配。 这就需要动态路由匹配了。动态路由 由/:表示斜杠后面的参数可以是任何内容 router文件夹中 index.js 匹配路由
// 动态字段以冒号开始
{ path: '/users/:id', component: User },
现在像 /users/johnny 和 /users/jolyne 这样的 URL 都会映射到同一个路由。
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 useRoute().params.id 的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户。
APP.VUE router-link中路径设置
<router-link to="/user/123">Go to User</router-link>
组件中获取id
<script setup>
import { useRoute } from "vue-router";
// console.log(useRoute());
console.log(useRoute().params.id);
</script>
匹配所not found
写一个notfound页面,里面展示资源找不到的时候页面显示的内容 将not found的放在最后,路由从上到下查找都不匹配,找到最后的时候匹配查找到这个位置的所有路由,说明404 not found
// 用到正则表达式,说明捕获所有路由,404 not found
{ path: "/:path(.*)", component: NotFound },
路由上的正则
{
//后面的参数必须是数字
path: "/new/:id(\\d+)",
path: "/new/:id+",//参数个数有1个或以上
path: "/new/:id*",//参数有0个或以上
path: "/new/:id(\\d+)*",
component: New,
},
设置导航
<router-link :to="/new/456" >Go to New</router-link>
嵌套路由
在同一个组件中,点击样式一,显示组件一的内容。点击样式二,显示组件二的内容
父组件中嵌套两个组件,这两个组件的路由写进父组件的children数组中,注意此处的路由不需要/号
//嵌套路由,一个组件的 UI 由多层嵌套的组件组成
{
path: "/parent",
component: Parent,
alias: ["/father", "/mother", "/fuqin"], //取别名,浏览器上三个名字都可以访问Parent页面
children: [
{ path: "styleone", component: StyleOne },
{ path: "styletwo", component: StyleTwo },
],
},
父组件的组件写法,如何把子组件嵌套进父组件中
<template>
<div>
<h2>父组件Parent</h2>
<h2>嵌套路由</h2>
<!-- router a标签,点击即可将组件呈现在router-link中 -->
<router-link to="/parent/styleone">样式一</router-link>
<router-link to="/parent/styletwo">样式二</router-link>
<!-- 样式一样式二展现在route-view中 -->
<router-view></router-view>
</div>
</template>
app.vue中设置导航
<router-link to="/parent">Go to Parent</router-link>
编程式导航
路由表配置
可以使用router可以导航到不同的url,可以使用router.push方法。这个方法回向history栈添加一个新的记录。所以用户点击浏览器后退按钮时,会返回之前的url.
当你点击 <router-link> 时,内部会调用这个方法,所以点击 <router-link :to="..."> 相当于调用 router.push(...) :
从page--->(跳转到)new
{ path: "/page", component: Page },
{
// name 命名路由,在router-link上 to= { name: 'new', params: { id: 135 } }
name: "new",
path: "/new/:id(\\d+)*",
component: New,
}
page.vue.page页面跳转验证:this.$router.push的使用
<template>
<div>
<h3>跳转</h3>
<button @click="goPage">跳转页面</button>
</div>
</template>
<script>
export default {
methods: {
goPage: function () {
// console.log(this.$router);
this.$router.push("/about");
//如果条件成立才进行跳转
if (123 === 123456) {
// this.$router.push("/");
// }
//传入对象,但是属性path和params不能同时存在
this.$router.push({path:"/new/1203"});
this.$router.push({name:"new",params:{id:'987'}}); //new/987
//带问号
this.$router.push({ path: "/about", query: { name: "query" } });// /about?name=query
},
},
};
替换当前页面
它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。
//替换当前位置,以下两条语句等价
this.$router.push({ path: "/about",replace:true }); //替换当前位置
this.$router.replace({ path: "/about"});
在历史堆栈中前进/后退
<template>
<div>
<h3>About</h3>
<button @click="goBack">后退</button>
</div>
</template>
<script setup>
import { useRoute } from "vue-router"; // console.log(useRoute());
console.log(useRoute().params.id);
useRoute()替换this.$router
//前进或后退
goBack: function () {
this.$router.go(-1); //负1表示后退 前一个页面
// this.$router.go(1);//正1表示前进
// this.$router.go(n);//前进或后退n步
//this.$router.back(); //等于go(-1);
// this.$router.forward() //等于go(1);
}
import { useRoute } from "vue-router"; // console.log(useRoute()); console.log(useRoute().params.id);
</script>
命名路由
在路由表中给路由添加一个属性name,这有以下优点:
- 没有硬编码的 URL
params的自动编码/解码。- 防止你在 url 中出现打字错误。
- 绕过路径排序(如显示一个)
{
name: "new",
path: "/new/:id(\\d+)*",
component: New,
},
导航跳转这样写
<router-link :to="{ name: 'new', params: { id: 123 } }" >Go to New</router-link>
或这样写
this.$router.push({name:"new",params:{id:'987'}}); //new/987
<!-- <router-link to="/new/123">Go to New</router-link> -->
命名路由
同一个路由展示多个视图,这几个视图都是同级的关系,和之前的嵌套路由不一样 路由配置,在shop路由中,同时展示ShopMain、ShopTop和ShopFoter三个同级组件
{
path: "/shop/:id",
components: {
default: ShopMain,
// 前面的属性名与 `<router-view>` 上的 `name` 属性匹配
Shoptop: ShopTop,
ShopFoter: ShopFoter,
},
//是否给子组件传参 true传参,false不传参
props: { default: true, Shoptop: true, ShopFoter: false },
},
html/app.vue组件
这三个router-view分别展示Shoptop、ShopMain、ShopFoter
<router-link to="/shop/gw">Go to Shop</router-link>
<router-view name="Shoptop"></router-view>
<router-view></router-view>
<router-view name="ShopFoter"></router-view>
重定向与别名
//重定向,使得"/"和 "/home"能访问同一个页面,redirect后面必须跟上已经定义好的路由
{
path: "/",
// redirect: "/home", //第一种重定向方式 ,取用path:中的值
// redirect: {name:"home"} //命名路由
redirect: (to) => {
console.log(to);
return { path: "/home" };//返回对象
},
重定向的时候,redirect后面需要跟着已经定义好的路由,path是新的名字,通过path上的名字,可以跳转到redirect后面接的路由 redirect后面有三种写法: 取别名
{
path: "/parent",
component: Parent,
alias: ["/father", "/mother", "/fuqin"],
}
传递参数
当 props 设置为 true 时,route.params 将被设置为组件的 props
const routes = [{ path: '/user/:id', component: User, props: true }]
在组件中通过defineProps接受从路由中传递过来的/:id的值
<script setup>
const props=defineProps({
id:String
})
console.log(props);
console.log(props.id);
</script>
选项式API
<script>
export default {
props: ['id'],
mounted() {
console.log(this.$route.params.id);
console.log(this.id);
},
};
</script>
命名视图
对于有命名视图的视图,必须为每个视图定义props,确定是否传递数据
const routes = [
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
对象模式
当 props 是一个对象时,它将原样设置为组件 props。当 props 是静态的时候很有用。
const routes = [
{
path: '/promotion/from-newsletter',
component: Promotion,
props: { newsletterPopup: false }
}
]
函数模式
你可以创建一个返回 props 的函数。这允许你将参数转换为其他类型,将静态值与基于路由的值相结合等等。
const routes = [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]
URL /search?q=vue 将传递 {query: 'vue'} 作为 props 传给 SearchUser 组件。
请尽可能保持 props 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 vue 才可以对状态变化做出反应。
历史模式
Hash模式
const router = createRouter({
// 4. 内部提供了 history 模式的实现。
// 使用 hash 模式,有# ,不会向服务器发送数据
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
});
HTML5模式
const router = createRouter({
// 4. 内部提供了 history 模式的实现。
//HTML5模式,正常的url,需要后端人员配置后台
history: createWebHistory(),
routes, // `routes: routes` 的缩写
});
导航守卫
路由守卫
全局守卫
每一次跳转都会触发,回调函数
// 全局守卫 关卡
router.beforeEach((to,from,next)=>{
console.log(to);
console.log(from);
// 满足条件才能通行
if(123==123){
next();//通行证
}
})
to:目标路由
from:原来的路由
next:通行证,可选参数,不带这个参数的时候不验证,直接通过。带这个参数,表示可以添加验证,验证成功,条件成立才进行跳转。例如登陆验证时候的token
每路守卫
写在路由表中
{
path: "/about",
component: About,
//每路守卫 进入about路由关卡
beforeEnter: (to, from, next) => {
console.log(to);
console.log(from);
if (123 === 123) {
//在个人中心,这里一般是token,是否登录完成
next(); //通行证
}
},
},
组件内守卫
组件内守卫有三个验证,进入组件之前,组件内路由变化时,离开组件
<script>
export default {
data() {
return {
routeage: 18,
};
},
// 进入组件之前是拿不到组件数据的,组件数据通过next拿到,vm代表此组件对象
beforeRouteEnter(to, from, next) {
console.log(to);
console.log(from);
//通过vm拿到组件实例,此处vm代表new.vue对象
next((vm) => {
console.log(vm.routeage);
});
console.log("路由进入组件之前");
},
beforeRouteUpdate() {
console.log("路由更新组件之前");
},
beforeRouteLeave() {
console.log("路由离开组件之前");
}
</script>
路由懒加载
当项目打包上线时,包过大,会影响页面加载,可以将不同路由对应的组件分割成代码块,当路由被访问时才加载相对应的组件 动态导入
// 路由懒加载,在需要的时候才导入,使用关键字About代替路径
const About = () => import("../views/About.vue");
路由配置
{
path: "/about",
component: About,
},