记录一下Vue Router 使用学习,本人在日常使用的一个总结纪录;写的不好勿喷!!! 如有不对,欢迎大神们赐教!!!
Vue Router 地址:https://router.vuejs.org/zh/introduction.html Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。
1.安装 vue-router :
方式一:直接下载 / CDN
直接下载: https://unpkg.com/vue-router@4 Unpkg.com 提供了基于 npm 的 CDN 链接。上述链接将始终指向 npm 上的最新版本。 你也可以通过像 https://unpkg.com/vue-router@4.0.15/dist/vue-router.global.js 这样的 URL 来使用特定的版本或 Tag。 方式二:使用npm 安装
# vue-router 3x
npm install vue-router --save
//或
cnpm install vue-router --save
# vue-router 4x
npm install vue-router@4 --save
//或
cnpm install vue-router@4 --save
2.在router/index.js(路由文件)中。
(vue-router 3x)路由文件
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
(vue-router 4x)路由文件
import {createRouter, createWebHashHistory} from 'vue-router';
import Login from '../views/login.vue'
const routes = [
{
path: '/',
name: 'Home',
component: () => import( '../views/Home.vue')
},
{ path: '/login', name:'Login', component: Login }
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
3.入门使用:
HTML方式
<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/vue-router@4"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
JavaScript方式 在main.js中
Vue2中使用
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
在 vue3 中使用
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// 创建一个应用实例。
const app = createApp(App)
整个应用支持路由。
app.use(router)
//将应用实例挂载在一个容器元素中。
app.mount('#app')
通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由。
4、JavaScript使用路由,在web页面中
- 根组件的模板里面放上
- 路由跳转
<router-link to="/home">首页</router-link>
<router-link to="/news">新闻</router-link>
动态路由 (编程式路由传参)
路径参数(通过 params 传递)
在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数 .
- 路径参数 用冒号
: 表示。 - 当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params 的形式暴露出来。
- 同一个路由中设置有多个路径参数,都会映射到 $route.params 上的相应字段
import Details from '@/components/Details'
const routes = [
{ path: 'details/:id', name: "details", component: Details },
]
router.push() 方法的参数可以是一个字符串路径,或者一个描述地址的对象。
//选项式API写法
<script >
export default {
metheds: {
toDetails() {
// 字符串路径
this.$router.push('/details/001')
// 带有路径的对象
this.$router.push({path: '/details/001'})
// 命名路由,路由配置时,需要 name 字段
this.$router.push({ name: 'details', params: { id: '001' } })
}
}
}
</script>
/*
Vue3.2,引入语法糖;
1、在 Vue3.2 之前变量必须 return 出来,template中才能使用;
2、而在 Vue3.2 中只需要在 script 标签上加上 setup 属性,无需 return,template 便可直接使用
如何使用setup语法糖
只需在 script 标签上写上setup
<script setup></script>
*/
//组合式API
<script setup>
const toDetails = () => {
// 字符串路径
this.$router.push('/details/001')
// 带有路径的对象
this.$router.push({path: '/details/001'})
// 命名路由,路由配置时,需要 name 字段
this.$router.push({ name: 'details', params: { id: '001' } })
}
</script>
注意,如果提供了 path,params 会被忽略:
响应路由参数的变化
使用带有参数的路由时需要注意的是,当用户从 /details/12 导航到 /details/16 时,相同的组件实例将被重复使用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用。 要对同一个组件中参数的变化做出响应的话,watch(监听)
r
o
u
t
e
对象上的任意属性。
‘
route 对象上的任意属性。 `
route对象上的任意属性。‘route对象上的属性:fullPath、hash、query、matched、meta(路由元信息)、name、params、path(路径)等属性`
const Details = {
template: '...',
created() {
this.$watch(
() => this.$route.params,
(toParams, previousParams) => {
}
)
},
}
const Details = {
template: '...',
async beforeRouteUpdate(to, from) {
this.userData = await fetchUser(to.params.id)
},
}
通过 query 传递
这种情况下 query (查询参数)传递的参数会显示在 url 后面,如:/details/001?kind=car 。
this.$router.push('/details/001?kind=car')
this.$router.push({ path: '/details/001', query: { kind: "car" }})
this.$router.push({ name: 'details', params: { id: '001' }, query: { kind: 'car' }})
通过 hash 传递
通过此方式,url 路径中带有 hash,例如:/details/001#car 。
this.$router.push('/details/001#car')
this.$router.push({ path: '/details/001', hash: '#car'})
this.$router.push({ name: 'details', params: { id: '001' }, hash: 'car'})
通过 props 进行传递
组件中使用 $route 会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的 URL。 以解耦的方式使用 props 进行参数传递,主要是在路由配置中进行操作。
- 1.布尔模式
当 props 设置为 true 时,route.params 将被设置为组件的 props const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const routes = [{ path: '/user/:id', component: User, props: true }]
const routes = [
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
- 2.对象模式
当 props 是一个对象时,它将原样设置为组件 props。当 props 是静态的时候很有用。
const routes = [
{
path: '/hello',
component: Hello,
props: { name: 'World' }
}
]
const Hello = {
props: {
name: {
type: String,
default: 'Vue'
}
},
template: '<div> Hello {{ name }}</div>'
}
- 3.函数模式
你可以创建一个返回 props 的函数。这允许你将参数转换为其他类型,将静态值与基于路由的值相结合等等。
//路由配置
const routes = [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]
// URL /search?q=vue 将传递 {query: 'vue'} 作为 props 传给 SearchUser 组件。
// 注意:请尽可能保持 props 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 vue 才可以对状态变化做出反应。
捕获所有路由或 404 Not found 路由
- 常规参数只匹配 url 片段之间的字符,用
/ 分隔。 - 匹配任意路径,我们可以使用自定义的 路径参数 正则表达式
const routes = [
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
{ path: '/user-:afterUser(.*)', component: UserGeneric },
{ path: '/:orderId(\\d+)' },
{ path: '/:productName' },
{ path: '/:chapters+' },
{ path: '/:chapters*' },
{ path: '/users/:userId?' },
]
确保转义反斜杠( \ ),就像我们对 \d (变成\d)所做的那样,在 JavaScript 中实际传递字符串中的反斜杠字符。
* 在技术上也标志着一个参数是可选的,但 ? 参数不能重复。
重定向和别名
- redirect(重定向)
重定向也是通过 routes 配置来完成,
const routes = [{ path: '/home', redirect: '/' }]
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]
const routes = [
{
path: '/search/:searchText',
redirect: to => {
return { path: '/search', query: { q: to.params.searchText } }
},
},
{
path: '/search',
},
]
- alias(别名)
通过别名,你可以自由地将 UI 结构映射到一个任意的 URL,而不受配置的嵌套结构的限制。使别名以 / 开头,以使嵌套路径中的路径成为绝对路径。 const routes = [{ path: '/', component: Homepage, alias: '/home' }]
导航守卫
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
-
- beforeEach (全局前置守卫)
在路由文件(router/index.js)中,使用 router.beforeEach 注册一个全局前置守卫 beforeEach 添加一个导航守卫,在任何导航前执行。返回一个删除已注册守卫的函数。 // 创建路由
//createRouter:创建一个可以被 Vue 应用程序使用的路由实例。
const router = createRouter({ ... })
//添加导航守卫
router.beforeEach(async (to, from) => {
/*
每个守卫方法接收两个参数:
to: 即将要进入的目标 用一种标准化的方式
from: 当前导航正要离开的路由 用一种标准化的方式
一个可选参数:
next:
返回:
false: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像你调用 router.push() 一样,你可以设置诸如 replace: true 或 name: 'home' 之类的配置。当前的导航被中断,然后进行一个新的导航,就和 from 一样。
如果遇到了意料之外的情况,可能会抛出一个 Error。这会取消导航并且调用 router.onError() 注册过的回调。
*/
// 返回 false 以取消导航
return false
});
/*
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
*/
//注册全局守卫,三个参数
router.beforeEach(async(to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
- 2.beforeResolve(全局解析守卫)
beforeResolve:添加一个导航守卫,在导航即将解析之前执行。在这个状态下,所有的组件都已经被获取,并且其他导航守卫也已经成功。返回一个删除已注册守卫的函数。router.beforeResolve(async to => {
if (to.meta.requiresCamera) {
try {
await askForCameraPermission()
} catch (error) {
if (error instanceof NotAllowedError) {
return false
} else {
throw error
}
}
}
})
- 3.afterEach(全局后置钩子 )
对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。 - 4.beforeEnter(路由独享的守卫)
- 在进入特定于此记录的守卫之前。注意如果记录有重定向属性,则 beforeEnter 无效。
- beforeEnter 守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发。
- 它们只有在 从一个不同的 路由导航时,才会被触发。
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
return false
},
},
]
- 5.组件内的守卫
可以在路由组件内直接定义路由导航守卫(传递给路由配置的)
beforeRouteEnter 路由进入守卫
- 在渲染该组件的对应路由被验证前调用
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。 beforeRouteEnter (to, from, next) {
next(vm => {
})
}
beforeRouteUpdate 路由更新守卫
- 在当前路由改变,但是该组件被复用时调用
- 组件已经挂载好了,导航守卫可以访问组件实例
this beforeRouteUpdate (to, from) {
this.name = to.params.name
}
beforeRouteLeave 路由离开守卫
- 在导航离开渲染该组件的对应路由时调用
- 与
beforeRouteUpdate 一样,它可以访问组件实例 this beforeRouteLeave (to, from) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (!answer) return false
}
常用相关API
- createRouter
创建一个可以被 Vue 应用程序使用的路由实例。const routes = [
{
path: '/',
name: 'Home',
component: () => import( '../views/Home.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: routes
})
- createWebHistory
创建一个 HTML5 历史,即单页面应用程序中最常见的历史记录。应用程序必须通过 http 协议被提供服务。createWebHistory()
createWebHistory('/folder/')
- createWebHashHistory
创建一个 hash 历史记录。对于没有主机的 web 应用程序 (例如 file://),或当配置服务器不能处理任意 URL 时这非常有用。 注意:如果 SEO 对你很重要,你应该使用 createWebHistory。// at https://example.com/folder
createWebHashHistory() // 给出的网址为 `https://example.com/folder#`
createWebHashHistory('/folder/') // 给出的网址为 `https://example.com/folder/#`
// 如果在 base 中提供了 `#`,则它不会被 `createWebHashHistory` 添加
createWebHashHistory('/folder/#/app/') // 给出的网址为 `https://example.com/folder/#/app/`
// 你应该避免这样做,因为它会更改原始 url 并打断正在复制的 url
createWebHashHistory('/other-folder/') // 给出的网址为 `https://example.com/other-folder/#`
// at file:///usr/etc/folder/index.html
// 对于没有 `host` 的位置,base被忽略
createWebHashHistory('/iAmIgnored') // 给出的网址为 `file:///usr/etc/folder/index.html#`
Router 方法
- addRoute
- 添加一条新的路由记录作为现有路由的子路由。
- 如果路由有一个
name ,并且已经有一个与之名字相同的路由,它会先删除之前的路由。 - 函数签名
addRoute(parentName: string | symbol, route: RouteRecordRaw): () => void
- parentName(类型: string | symbol ) 父路由记录,route 应该被添加到的位置;可不写
- route (l类型:RouteRecordRaw) 要添加的路由记录
- 使用
router.addRoute("layout", item)
const routes_404 = {
path: "/:pathMatch(.*)*",
hidden: true,
component: () => import( '@/views/other/404'),
}
const router = createRouter({
history: createWebHashHistory(),
routes: [{{ path: 'details/:id', name: "details", component: () => import( '@/views/Details') }}]
})
router.addRoute(routes_404)
- onError
- 添加一个错误处理程序,在导航期间每次发生未捕获的错误时都会调用该处理程序。
- 这包括同步和异步抛出的错误、在任何导航守卫中返回或传递给 next 的错误,以及在试图解析渲染路由所需的异步组件时发生的错误。
router.onError((error) => {
//error :注册的错误处理程序
NProgress.done();
ElNotification.error({
title: '路由错误',
message: error.message
});
});
- push
- 通过在历史堆栈中推送一个 entry,以编程方式导航到一个新的 URL。
- push(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>
- to(类型RouteLocationRaw): 要导航到的路由地址
- removeRoute
- 通过名称删除现有路由。
removeRoute(name: string | symbol): void
- name string | symbol 要删除的路由名称
router.removeRoute('about') - getRoutes
获取所有 路由记录的完整列表。 getRoutes(): RouteRecord[] router.getRoutes() - go
- 允许你在历史中前进或后退。
go(delta: number): void
- back
|