简单使用
下载路由模块
npm i vue-router@4
使用
- 在src下面创建router文件夹
- 在文件夹中创建index.js
- 在main.js中引入路由,并全局注册
main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router"; // 导入路由
createApp(App)
.use(router) //注册路由(全局的组件,指令,)
.mount("#app");
路由配置文件
import {
createRouter,
createWebHashHistory,
createWebHistory,
} from "vue-router";
import Film from '../views/Film.vue'
import Cinema from '../views/Cinema.vue'
import Center from '../views/Center.vue'
const routes = [
{ path: '/film', component: Film },
{ path: '/cinema', component: Cinema },
{ path: '/center', component: Center },
]
const router = createRouter({
history: createWebHashHistory(), // hash模式 带有 # 号的路由形式
// history:createWebHistory(), // 不带 # 号的形式
routes, // routes:routes 的简写
});
export default router;
重定向
redirect : " 要重定向到哪去 "
{
// 重定向
path: "/",
redirect: "/films", // 重定向到路径为 /films 的页面
},
懒加载
- 方案一(常用):使用箭头函数+ import动态加载
{
path: "/mine",
component: () => import("../views/Mine.vue"), // 懒加载
}
- 方案二:使用箭头函数+ require动态加载
{
path:"/mine",
componenty:resolve => require(['@/componnets/list'],resolve) // @是src的别名
}
别名和嵌套路由
- alias:别名
- children:嵌套路由
{
path: "/films", // url路径
component: Films, // 路径加载组件
alias: "/dianying", // alias 别名
redirect: "/films/nowPlaying", // 重定向到:正在热映
// 嵌套路由
children: [
{
// 写法 1
path: "/films/nowPlaying", // 使用:/films/nowPlaying
component: nowPlaying,
},
{
// 写法 2
path: "comingSoon", // 使用:/films/comingSoon
component: comimgSoon,
},
],
},
声明式导航 和 编程式导航
声明式导航
1. 默认的 router-link 写法:
- router-link默认是转换为
a标签, - 属性:
- to 代表跳转的路径
- active-class 表示被选中的样式
<ul>
<li><router-link to="/film" active-class="active">film</router-link></li>
<li><router-link to="/cinema" active-class="active">cinema</router-link></li>
<li><router-link to="/center" active-class="active">center</router-link></li>
</ul>
2. 自定义 router-link 写法
- 自定义router-link的标签中的属性:
- to 代表跳转的路径
- custom 代表自定义router-link的标签,
- v-slot 作用域插槽,用来取router-lik中提供的属性或方法
- navigate 用来跳转的函数,
- isActive 用来判断当前的标签是否被选中,返回值为true和false
<ul>
<router-link to="/film" customv-slot="{ navigate, isActive }">
<li @click="navigate" :class="isActive ? 'active' : ''">
films
</li>
</router-link>
<router-link to="/cinema" customv-slot="{ navigate, isActive }">
<li @click="navigate" :class="isActive ? 'active' : ''">
cinema
</li>
</router-link>
</ul>
编程式导航
- 关键字:
router.push()
// 字符串路径
router.push('/users/eduardo')
// 带有路径的对象
router.push({ path: '/users/eduardo' })
// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })
// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })
动态路由 + 组件内守卫
动态路由
- 通过 传递参数 来加载展示:结构相同内容不同的数据
const routes = [
{
// query传参 ?id=123
// path: "/film",
// 通过 /id 的方式传参
path: "/film/:myid",
component: Film,
},
]
组件内守卫
- 在组件内部写 钩子函数
beforeRouteEnter(to, from) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
},
beforeRouteUpdate(to, from) {
// 在当前路由改变,并且该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
},
beforeRouteLeave(to, from) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
},
使用
import {useRouter} from 'vue-router'
const router = useRouter()
// 猜你喜欢点击跳转到对应详情页
const detailsPage = (id) => {
router.push(`/film/${id}`);
// 在 onBeforeRouteUpdate 钩子中,发起ajax请求,重新请求数据
};
// 组件内部守卫
// 场景设定:猜你喜欢,点击对应按钮后跳转到对应电影的详情页
// 可以看到 mounted 生命周期函数只会执行一次,
// 即使再次点击喜欢的电影,页面也不会再次发起ajax请求新的数据
// 这事就需要利用router中的生命周期函数,当路由变化时,重新发起ajax请求
onBeforeRouteUpdate(async (newRoute) => {
let { myid } = newRoute.params; // 通过 /id 的方式传值
let {
data: {
data: { film },
},
} = await axios({
url: `https://m.maizuo.com/gateway?filmId=${myid}&k=7819881`,
headers: {
"X-Host": "mall.film-ticket.film.info",
},
});
// 页面显示数据
filmInfo.value = film;
// 回到页面顶部
window.scrollTo(0, 0);
});
全局路由拦截
- 在路由文件中写
const routes = [
{
path: "/mine",
component: () => import("../views/Mine.vue"), // 懒加载
meta: {
myrequiresAuth: true, // 使用拦截
},
},
]
// 全局路由拦截
// 场景设定:需要登录成功之后才能查看我的页面
router.beforeEach((to, from, next) => {
// 在routes数组,要拦截的对象中添加 meta
let token = localStorage.getItem("token");
if (to.path != "/login" && !token && to.meta.myrequiresAuth) {
next("/login");
} else {
next();
}
});
路由模式
- 分为两种:
- createWebHashHistory() 创建的 hash 模式
- createWebHistory() 创建的 HTML5 模式
createWebHashHistory -- hash 模式
- 它在内部传递的实际 URL 之前使用了一个哈希字符(
#) - 这里的实际路径为
#/films
import {createRouter , createWebHashHistory} from "vue-router";
import Film from '../views/Film.vue'
const routes = [{ path: '/film', component: Film }]
const router = createRouter({
history: createWebHashHistory(), // hash模式 带有 # 号的路由形式
routes, // routes:routes 的简写
});
export default router;
createWebHistory -- HTML5 模式
- 路径中不带
#
import {createRouter , createWebHistory} from "vue-router";
import Film from '../views/Film.vue'
const routes = [{ path: '/film', component: Film }]
const router = createRouter({
history: createWebHistory(), // HTML5模式
routes, // routes:routes 的简写
});
export default router;