vue路由_router
Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。
客户端路由的作用是在单页应用 (SPA) 中将浏览器的 URL 和用户看到的内容绑定起来。当用户在应用中浏览不同页面时,URL 会随之更新,但页面不需要从服务器重新加载。
Vue Router 基于 Vue 的组件系统构建,你可以通过配置路由来告诉 Vue Router 为每个 URL 路径显示哪些组件。
一、安装router
如果你的项目没有router,那需要先安装。
npm install vue-router@4
如果你的项目是新的项目,使用这个命令创建的项目,那么他自动包含router
npm create vue@latest
二、创建路由实例
在src下创建一个文件夹,router,新建一个文件index.js
// 引入需要的模块
import { createRouter, createWebHistory } from "vue-router";
import InDex from "../components/HelloWorld.vue";
// 下面使用了es6的对象增强写法,命名必须是routes
const routes = [{//默认展示,这是主页面路由必须加斜杠 /path: "/",component: InDex,},{path: "/plan",//路由懒加载component: () => import("../components/plan.vue"),},
];// 创建路由
const router = createRouter({history: createWebHistory(),routes,
});// 导出路由
export default router;
history是历史记录模式,有三种:
①HTML5 模式
用 createWebHistory()
创建 HTML5 模式,推荐使用这个模式。
当使用这种历史模式时,URL 会看起来很 "正常",例如 https://example.com/user/id
。。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 https://example.com/user/id
,就会得到一个 404 错误。这就尴尬了。
不用担心:要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html
相同的页面。
②Hash 模式
hash 模式是用 createWebHashHistory()
创建的。它在内部传递的实际 URL 之前使用了一个井号(#
)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。
③Memory 模式
Memory 模式不会假定自己处于浏览器环境,因此不会与 URL 交互也不会自动触发初始导航。这使得它非常适合 Node 环境和 SSR。它是用 createMemoryHistory()
创建的,并且需要你在调用 app.use(router)
之后手动 push 到初始导航。虽然不推荐,你仍可以在浏览器应用程序中使用此模式,但请注意它不会有历史记录,这意味着你无法后退或前进。
三、注册路由器插件
在main.js文件内:
一旦创建了我们的路由器实例,我们就需要将其注册为插件,这一步骤可以通过调用 use()
来完成。
js
import router from './router/index'createApp(App).use(router).mount('#app')
或等价地:
js
import router from './router/index'const app = createApp(App)
app.use(router)
app.mount('#app')
和大多数的 Vue 插件一样,use()
需要在 mount()
之前调用。
四、展示路由组件
在跟组件APP.vue中:
<template><div class="appStyle"><router-view v-slot="{ Component }"><!-- keep-alive 是Vue提供的一个抽象组件,主要用于保留组件状态或避免重新渲染。 --><keep-alive><component :is="Component" /></keep-alive></router-view></div>
</template>
RouterView
组件可以使 Vue Router 知道你想要在哪里渲染当前 URL 路径对应的路由组件。它不一定要在 App.vue
中,你可以把它放在任何地方,但它需要在某处被导入,否则 Vue Router 就不会渲染任何东西。
五、路由页面跳转
1.编程式导航
在页面引入:
import router from "@/router/index";
① 跳到一个新页面
它会在浏览器的历史记录堆栈中添加一个新条目,允许用户使用浏览器的后退按钮导航回上一页。
router.push(`/user`)
② 替换当前页面
它替换浏览器历史堆栈中的当前条目,而不是添加新条目。这意味着用户将无法使用浏览器的后退按钮导航回上一页。
router.replace(`/user`)
2.声明式导航
<RouterLink to="/about">Go to About</RouterLink>//传参
<router-link :to="{ path: '/about', query: { id: 1 } }">About</router-link>
router-link
是 Vue Router 提供的一个组件,用于在 Vue 应用中创建导航链接。它会根据 to
属性的值动态生成一个 <a>
标签(默认情况下),并绑定相应的事件来触发路由跳转。
六、传参与接收参数
传递参数:
router.push({ path: '/search', query: { data:666 } });
接收参数:
import { useRoute} from 'vue-router';
const route = useRoute();const data= route.query.data;
router是路由器实例,route是当前路由。
七、导航守卫
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
1.全局前置守卫
const router = createRouter({ ... })//to,要跳转去的路由
//from,要离开的路由
router.beforeEach((to, from) => {// ...// 返回 false 以取消导航return false
})
可以返回的值如下:
false
: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from
路由对应的地址。- 一个路由地址: 通过一个路由地址重定向到一个不同的地址,如同调用
router.push()
,且可以传入诸如replace: true
或name: 'home'
之类的选项。它会中断当前的导航,同时用相同的from
创建一个新导航。
router.beforeEach(async (to, from) => {if (// 检查用户是否已登录!isAuthenticated &&// ❗️ 避免无限重定向to.name !== 'Login') {// 将用户重定向到登录页面return { name: 'Login' }}})
还有一个参数,next,表示继续跳转路由,进入to要去的路由。
router.beforeEach((to, from, next) => {if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })else next()
})
2.全局解析守卫
它在每次导航时都会触发,不同的是,解析守卫刚好会在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用。这里有一个例子,根据路由在元信息中的 requiresCamera
属性确保用户访问摄像头的权限:
router.beforeResolve(async to => {if (to.meta.requiresCamera) {try {await askForCameraPermission()} catch (error) {if (error instanceof NotAllowedError) {// ... 处理错误,然后取消导航return false} else {// 意料之外的错误,取消导航并把错误传给全局处理器throw error}}}
})
router.beforeResolve
是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。
3.全局后置钩子
对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
router.afterEach((to, from) => {sendToAnalytics(to.fullPath)
})
4.在守卫内的全局注入
你可以在导航守卫内使用 inject()
方法。这在注入像 pinia stores 这样的全局属性时很有用。在 app.provide()
中提供的所有内容都可以在 router.beforeEach()
、router.beforeResolve()
、router.afterEach()
内获取到:
// main.ts
const app = createApp(App)
app.provide('global', 'hello injections')// router.ts or main.ts
router.beforeEach((to, from) => {const global = inject('global') // 'hello injections'// a pinia storeconst userStore = useAuthStore()// ...
})
5.路由独享的守卫
beforeEnter
守卫 只在进入路由时触发,不会在 params
、query
或 hash
改变时触发。例如,从 /users/2
进入到 /users/3
或者从 /users/2#info
进入到 /users/2#projects
。它们只有在 从一个不同的 路由导航时,才会被触发。
const routes = [{path: '/users/:id',component: UserDetails,beforeEnter: (to, from) => {// reject the navigationreturn false},},
]
6.组件内的守卫
可以在路由组件内直接定义路由导航守卫(传递给路由配置的):
<script>
export default {beforeRouteEnter(to, from) {// 在渲染该组件的对应路由被验证前调用// 不能获取组件实例 `this` !// 因为当守卫执行时,组件实例还没被创建!},beforeRouteUpdate(to, from) {// 在当前路由改变,但是该组件被复用时调用// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`},beforeRouteLeave(to, from) {// 在导航离开渲染该组件的对应路由时调用// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`},
}
</script>