Vue Router 是 Vue.js 官方提供的路由管理器,它与 Vue.js 核心深度集成,使得构建单页面应用(SPA)变得容易。在单页面应用中,所有视图和组件都通过路由来管理和切换,而不是传统的整页刷新。
在本课文中将介绍Vue Router的一些常用方法。
视频🎞️:Router 4
安装
新建项目
npm create vite@latest
创建项目时选择Customize with create-vue,并且选择引入 Vue Router 进行单页面应用开发,其他选项可以按需进行选择。
这样创建的项目已经初始化好Vue Router文件配置。可以开箱即用。
已有项目
- 在终端中输入
npm install vue-router@4
- 创建
router/index.js
javascript">import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [... // 页面路由配置]
})export default router
- 在main.js中引入
router/index.js
,并且通过app.use()
明确地安装路由功能
javascript">... ...
import { createApp } from 'vue'import App from './App.vue'
import router from './router' // 导入创建的jsconst app = createApp(App)app.use(router) // 安装路由功能app.mount('#app')
页面组件的内容将在<RouterView/>
中渲染。
routes配置
history模式配置
HTML5 模式(推荐)
createWebHistory()
url效果:http://example.com/myroute
url看上去和正常的链接一样干净,需要注意在生产环境中要进行配置,使得任何非静态资源请求(如 /about、/dashboard 等)都被重定向到应用的入口 HTML 文件(通常是 index.html),否则会出现404。
javascript">import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(), // HTML5 模式routes: [// ...]
})export default router
Hash 模式
createWebHashHistory()
url效果:http://example.com/#/myroute
它在内部传递的实际 URL 之前使用了一个哈希字符(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。但是seo效果不好。
javascript">import { createRouter, createWebHashHistory} from 'vue-router'const router = createRouter({0 history: createWebHashHistory(), // Hash 模式routes: [// ...]
})export default router
路由组件导入方法
静态导入
静态导入会在应用启动时随主资源一同加载,当模块多的时候容易造成首屏加载时间过长,
javascript">import { createRouter, createWebHistory } from 'vue-router'
// 静态导入页面组件
import HomeView from '../views/HomeView.vue'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',// 使用引入的路由组件component: HomeView }]
})export default router
懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。
javascript">import { createRouter, createWebHistory } from 'vue-router'
// 动态导入页面组件
const AboutView = () => import('../views/AboutView.vue')const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/about',name: 'about',component: AboutView }]
})export default router
路由传参
方式一:query
使用query传参会跟传统的参数一样,?
跟在url后面,多个参数以 &
隔开。
javascript">import {useRouter} from "vue-router";
const $router = useRouter()function onToView(){$router.push({path:'/user',query:{text:'UserView'}})// $router.push('/user?text=UserView') // 自己拼接url
}
方式二:params
需要先在路由配置中使用 :
+参数名
来配置参数
javascript">
routes: [// ...{path: '/user/:id', //配置id参数name: 'user',component: () => import('../views/UserView.vue'),}// ... ]
当使用path时,params属性会被忽略,所以要么使用name属性,或者自己拼接url;
javascript">import {useRouter} from "vue-router";
const $router = useRouter()function onToView(){let id = 0$router.push({name:'user',params:{id:id}})// $router.push(`/user/${id}`) // 自己拼接url
}
元信息
当需要一些信息附加到路由上时,可以通过配置路由元信息来实现,比如是否需要登录才能访问,设置页面切换过渡效果,是否要缓存该页面…
javascript">routes: [// ...{path: '/', name: 'home',meta: {checkLogin: true}, // 配置元信息component: () => import('../views/HomeView.vue'),}// ... ]
单独配置元信息不会起到任何作用,还需要写相应的代码来达成期望效果;
例如通过元信息配置部分页面需要使用<keep-alive/>
缓存
javascript"><template><router-view v-slot="{ Component }"><keep-alive :include="cacheRouteName"><component :key="$route.name" :is="Component" /></keep-alive></router-view>
</template><script setup>
import { useRouter } from "vue-router"const router = useRouter()// 从路由中获取带有缓存元数据的路由名称
const cacheRouteName = router.getRoutes().filter((item) => item.meta?.cache) // 过滤出带有缓存元数据的路由.map((item) => item.name) // 提取路由名称
</script>
路由守卫
路由守卫主要用来通过跳转或取消的方式守卫导航。
每个路由守卫接收两个参数
to
:代表即将要进入的路由from
:代表当前即将离开的路由
可选的第三个参数next
当设置该参数时,需要确保在路由守卫中执行一次next()
若未调用,则页面导航将被阻塞,无法正常跳转。它可以出现多次,但应只执行一次。
next方法中可以传递path来重定向到其它页面
javascript">router.beforeEach((to, from, next) => {if (/* 用户未登录 */) {next('/login'); // 通过 next 方法重定向到登录页} else {next(); // 继续正常跳转}
});
javascript">import { createRouter, createWebHistory } from 'vue-router';const router = createRouter({history: createWebHistory(),routes: [// 定义路由{ path: '/home', component: Home,// 路由独享的守卫beforeEnter: (to, from, next) => { // 在进入路由前执行的逻辑// 可以进行权限验证等操作next(); // 调用next()继续路由导航}},// 其他路由定义]
});// 全局前置路由守卫
router.beforeEach((to, from, next) => {// 在进入每个路由前执行的逻辑// 可以进行全局的权限验证等操作next(); // 调用next()继续路由导航
});export default router;