记录一下Vue Router 使用学习,本人在日常使用的一个总结纪录;写的不好勿喷!!!
如有不对,欢迎大神们赐教!!!
Vue Router 地址:https://router.vuejs.org/zh/introduction.html
Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。
方式一:直接下载 / 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
(vue-router 3x)路由文件
import Vue from 'vue' // 引入vue
import Router from 'vue-router' // 引入vue-router路由依赖
//定义路由组件
import HelloWorld from '@/components/HelloWorld' // 引入页面组件,命名为HelloWorld
// Vue全局使用Router
Vue.use(Router)
// 定义路由配置
export default new Router({
routes: [ //配置路由
{
path: '/', //链接路径
name: 'HelloWorld', //路由名称
component: HelloWorld //对应组件模板
}
]
})
(vue-router 4x)路由文件
import {createRouter, createWebHashHistory} from 'vue-router';
// 1. 定义路由组件.
import Login from '../views/login.vue'
// 2. 定义一些路由 ; 每个路由都需要映射到一个组件。
const routes = [
{
path: '/',
name: 'Home',
//路由懒加载 ,使用 webpack(需要 Webpack > 2.4),
component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
},
{ path: '/login', name:'Login', component: Login }
]
3. 创建路由实例并传递 `routes` 配置
const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes // `routes: routes` 的缩写
})
export default router
<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` 来指定链接 -->
<!--` ` 将呈现一个带有正确 `href` 属性的 `` 标签-->
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
Vue2中使用
import Vue from 'vue' // 引入vue
import App from './App' // 引入根组件
import router from './router' // 引入路由配置
//productionTip(2.2.0 新增) 设置为 false 以阻止 vue 在启动时生成生产提示。
Vue.config.productionTip = false // 关闭生产模式下给出的提示
// Vue.config.silent = true //取消 Vue 所有的日志与警告。
// 创建并挂载到 #app (会替换 #app)
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 访问当前路由。
首页
新闻
在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数 .
:表示。//定义路由组件
import Details from '@/components/Details' // 引入页面组件,命名为 Details
// 这些都会传递给 `createRouter`
const routes = [
// 动态字段以冒号开始
{ path: 'details/:id', name: "details", component: Details },
]
router.push() 方法的参数可以是一个字符串路径,或者一个描述地址的对象。
//选项式API写法
/*
Vue3.2,引入语法糖;
1、在 Vue3.2 之前变量必须 return 出来,template中才能使用;
2、而在 Vue3.2 中只需要在 script 标签上加上 setup 属性,无需 return,template 便可直接使用
如何使用setup语法糖
只需在 script 标签上写上setup
*/
//组合式API
注意,如果提供了 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) => {
// 对路由变化做出响应...
}
)
},
}
// 或者,使用 beforeRouteUpdate 导航守卫,它也可以取消导航:
const Details = {
template: '...',
async beforeRouteUpdate(to, from) {
// 对路由变化做出响应...
this.userData = await fetchUser(to.params.id)
},
}
这种情况下 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' }})
//组件通过 $route.query 获取数据,
// 要对同一个组件中参数的变化做出响应的话,你可以简单地 watch $route 对象上的任意属性,在这个场景中,就是 $route.query 。
通过此方式,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'})
//组件通过 $route.hash.slice(1) 获取数据
组件中使用 $route 会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的 URL。
以解耦的方式使用 props 进行参数传递,主要是在路由配置中进行操作。
props 设置为 true 时,route.params 将被设置为组件的 propsconst User = {
// 请确保添加一个与路由参数完全相同的 prop 名
props: ['id'],
template: 'User {{ id }}'
}
const routes = [{ path: '/user/:id', component: User, props: true }]
//注意:对于有命名视图的路由,你必须为每个命名视图定义 props 配置:
const routes = [
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
//路由配置
const routes = [
{
path: '/hello',
component: Hello,
props: { name: 'World' }
}
]
//组件内取数据
const Hello = {
props: {
name: {
type: String,
default: 'Vue'
}
},
template: ' Hello {{ name }}'
}
// 组件默认显示 Hello Vue,但路由配置了 props 对象,当路由跳转到 /hello 时,会显示传递过来的 name, 页面会显示为 Hello World。
//路由配置
const routes = [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]
// URL /search?q=vue 将传递 {query: 'vue'} 作为 props 传给 SearchUser 组件。
// 注意:请尽可能保持 props 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 vue 才可以对状态变化做出反应。
/ 分隔。const routes = [
// 将匹配所有内容并将其放在 `$route.params.pathMatch` 下
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
// 将匹配以 `/user-` 开头的所有内容,并将其放在 `$route.params.afterUser` 下
{ path: '/user-:afterUser(.*)', component: UserGeneric },
// /:orderId -> 仅匹配数字
{ path: '/:orderId(\\d+)' },
// /:productName -> 匹配其他任何内容
{ path: '/:productName' },
//可重复参数
// /:chapters -> 匹配 /one, /one/two, /one/two/three, 等
{ path: '/:chapters+' },
// /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
{ path: '/:chapters*' },
//通过使用 ? 修饰符(0 个或 1 个)将一个参数标记为可选:
// 匹配 /users 和 /users/posva
{ path: '/users/:userId?' },
]
确保转义反斜杠( \ ),就像我们对 \d (变成\d)所做的那样,在 JavaScript 中实际传递字符串中的反斜杠字符。
*在技术上也标志着一个参数是可选的,但?参数不能重复。
//是从 /home 重定向到 /
const routes = [{ path: '/home', redirect: '/' }]
//重定向的目标也可以是一个命名的路由
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]
//重定向的目标也可以是一个方法, 动态返回重定向目标
const routes = [
{
// /search/screens -> /search?q=screens
path: '/search/:searchText',
redirect: to => {
// 方法接收目标路由作为参数
// return 重定向的字符串路径/路径对象
return { path: '/search', query: { q: to.params.searchText } }
},
},
{
path: '/search',
// ...
},
]
/ 开头,以使嵌套路径中的路径成为绝对路径。const routes = [{ path: '/', component: Homepage, alias: '/home' }]vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
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()
})
router.beforeResolve(async to => {
if (to.meta.requiresCamera) {
try {
await askForCameraPermission()
} catch (error) {
if (error instanceof NotAllowedError) {
// ... 处理错误,然后取消导航
return false
} else {
// 意料之外的错误,取消导航并把错误传给全局处理器
throw error
}
}
}
})
//router.beforeResolve 是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// reject the navigation
return false
},
},
]
beforeRouteEnter 路由进入守卫
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
//注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫
beforeRouteUpdate 路由更新守卫
thisbeforeRouteUpdate (to, from) {
// just use `this`
this.name = to.params.name
}
beforeRouteLeave 路由离开守卫
beforeRouteUpdate 一样,它可以访问组件实例 thisbeforeRouteLeave (to, from) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (!answer) return false
}
//离开守卫 通常用来预防用户在还未保存修改前突然离开。该导航可以通过返回 false 来取消
const routes = [
{
path: '/',
name: 'Home',
//懒加载
component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: routes
})
createWebHistory() // 没有 base,应用托管在域名 `https://example.com` 的根目录下。
createWebHistory('/folder/') // 给出的网址为 `https://example.com/folder/`
// 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#`
name ,并且已经有一个与之名字相同的路由,它会先删除之前的路由。addRoute(parentName: string | symbol, route: RouteRecordRaw): () => void
router.addRoute("layout", item)//定义特殊路由
const routes_404 = {
path: "/:pathMatch(.*)*",
hidden: true,
component: () => import(/* webpackChunkName: "404" */ '@/views/other/404'),
}
// 创建路由实例
const router = createRouter({
history: createWebHashHistory(),
routes: [{{ path: 'details/:id', name: "details", component: () => import(/* webpackChunkName: "404" */ '@/views/Details') }}]
})
//添加路由
router.addRoute(routes_404)
router.onError((error) => {
//error :注册的错误处理程序
NProgress.done();
ElNotification.error({
title: '路由错误',
message: error.message
});
});
removeRoute(name: string | symbol): void
router.removeRoute('about')getRoutes(): RouteRecord[]router.getRoutes()go(delta: number): void
this.$router.go(-1):后退+刷新;
this.$router.go(0):刷新;
this.$router.go(1) :前进
this.$router.back():后退 ;
this.$router.back(0) 刷新;
this.$router.back(1):前进