一、vue router基础配置,从0到1搭路由骨架
p标签开头:“不少刚接触Vue.js的同学,一碰到vue - router配置就犯难:路由咋设置?页面咋跳转?碰到动态路由、嵌套路由更是一头雾水,今天咱就把vue - router配置拆成基础、场景、进阶三个层面,用大白话讲清楚配置逻辑,新手也能跟着一步步做~”
先装依赖,项目里咋引入vue - router?
要是Vue2项目,先通过npm安装:npm install vue - router@3
(Vue3对应@4版本),装完后,得在项目里新建路由文件,比如src/router/index.js
,文件里要做这几步:
- 导入Vue和VueRouter(Vue2用
Vue.use(VueRouter)
,Vue3是createRouter
和createWebHistory
这类API); - 定义路由规则数组,每个规则是
{path: '/路径', component: 对应组件}
; - 创建路由实例,配置模式(比如history模式去掉#);
- 导出实例,最后在main.js里把路由实例注入Vue根实例。
举个Vue2的简单例子:// src/router/index.js import Vue from 'vue' import VueRouter from 'vue - router' import Home from '@/views/Home.vue' import About from '@/views/About.vue'
Vue.use(VueRouter) // 注册插件
const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About } ]
const router = new VueRouter({ mode: 'history', // 选history模式,地址栏没#;hash模式有# routes })
export default router
然后在main.js里引入:
```js
import Vue from 'vue'
import App from './App.vue'
import router from './router' // 引入路由实例
new Vue({
router, // 注入路由
render: h => h(App)
}).$mount('#app')
最后在App.vue里加<router - view>
(显示匹配组件)和<router - link>
(跳转用,替代a标签):
<template> <div id="app"> <router - link to="/">首页</router - link> <router - link to="/about">lt;/router - link> <router - view></router - view> </div> </template>
路由模式选history还是hash?有啥区别?
简单说,hash模式地址栏带(比如http://xxx/#/about
),history模式没(http://xxx/about
)。
- hash模式:靠URL里的hash值(#后面部分)变化触发路由,兼容性好,不用后端配合;但地址栏有#,不太美观。
- history模式:用HTML5的history API(pushState、replaceState),地址更干净,但部署时得让后端配合——所有前端路由对应的404请求,都重定向到index.html,否则刷新会报404,如果是本地开发或简单项目,hash模式够稳;想地址好看,正式项目部署前得和后端约定好重定向规则。
常见场景配置:动态路由、嵌套路由、编程式导航
动态路由咋配?比如商品详情页要传ID
当页面结构一样,数据不同(像商品详情、用户详情),就用动态路由,配置时,在path里加:参数名
,组件里用$route.params
拿参数。
步骤:
- 路由规则里定义动态段:
{ path: '/product/:id', // :id是动态参数 name: 'ProductDetail', component: ProductDetail }
- 组件里接收参数:
<template> <div>商品ID:{{ $route.params.id }}</div> </template> <script> export default { mounted() { console.log(this.$route.params.id) // 打印路由参数 } } </script>
- 跳转时,
<router - link :to="{ name: 'ProductDetail', params: { id: 123 }}">商品123</router - link>
,或者编程式导航this.$router.push({ name: 'ProductDetail', params: { id: 123 }})
。
嵌套路由咋实现?比如后台管理页有侧边栏+内容区
嵌套路由就是“路由里套路由”,父组件里有<router - view>
显示子路由组件,配置时用children
数组。
举个后台管理的例子:
- 父组件
Layout.vue
结构:<template> <div> <aside>侧边栏</aside> <main> <router - view></router - view> <!-- 显示子路由组件 --> </main> </div> </template>
- 路由规则里配置children:
{ path: '/admin', component: Layout, children: [ { path: 'dashboard', // 注意:子路由path不加/,最终路径是/admin/dashboard name: 'Dashboard', component: Dashboard }, { path: 'settings', name: 'Settings', component: Settings } ] }
这样访问
/admin/dashboard
时,Layout组件渲染,同时Dashboard组件渲染到Layout里的<router - view>
。
编程式导航和<router - link>
有啥区别?啥时候用this.$router.push?
<router - link>
是声明式导航,适合模板里写跳转(比如导航栏按钮),编程式导航用this.$router.push/replace/go
这些方法,适合逻辑里触发跳转(比如点击按钮后判断权限再跳转)。
比如登录成功后跳转:
<template> <button @click="handleLogin">登录</button> </template> <script> export default { methods: { handleLogin() { // 登录逻辑... this.$router.push('/home') // 编程式导航跳转 } } } </script>
push
是添加新历史记录,replace
是替换当前记录(后退时不会回到上一个页面),go(n)
是前进或后退n步(类似浏览器history.go)。
进阶优化:路由守卫、懒加载、错误处理
路由守卫是干啥的?全局守卫和组件内守卫咋用?
路由守卫就是“路由跳转前/后做些操作”,比如权限判断、加载动画、埋点,分全局、路由独享、组件内三种。
-
全局守卫:
router.beforeEach((to, from, next) => {})
跳转前触发,要调用next()
放行/阻止,比如判断是否登录:// src/router/index.js router.beforeEach((to, from, next) => { const isLogin = localStorage.getItem('token') if (to.path === '/login' || isLogin) { next() // 登录页或已登录,放行 } else { next('/login') // 没登录,跳登录页 } })
router.afterEach((to, from) => {})
跳转后触发,不用next,适合做页面标题修改、埋点。 -
组件内守卫:
写在组件的js里,比如beforeRouteEnter
(进入前,组件实例还没创建,不能用this)、beforeRouteUpdate
(路由参数变化时,比如从/product/1到/product/2)、beforeRouteLeave
(离开前,比如提醒用户保存):<script> export default { beforeRouteEnter(to, from, next) { // 组件还没创建,this是undefined next(vm => { // vm是组件实例 vm.fetchData() // 可以调组件方法 }) }, beforeRouteUpdate(to, from, next) { // 路由参数变了,product/:id,id从1变2 this.id = to.params.id this.fetchData() next() }, beforeRouteLeave(to, from, next) { if (this.formDirty) { if (window.confirm('有未保存内容,确定离开?')) { next() } else { next(false) // 阻止跳转 } } else { next() } } } </script>
路由懒加载咋配?能优化首屏加载速度?
路由懒加载就是“用到哪个组件,再加载哪个组件”,减少首屏打包体积,配置时用动态import()语法。
原来的静态导入是import Home from '@/views/Home.vue'
,改成懒加载:
const Home = () => import('@/views/Home.vue') const About = () => import('@/views/About.vue') const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ]
这样每个组件会被打包成单独的chunk,访问对应路由时才加载,首屏加载更快,还能给懒加载加loading效果,
const Home = () => import(/* webpackChunkName: "home" */ '@/views/Home.vue')
webpack会给这个chunk命名,方便调试。
路由错误咋处理?比如404页面
配置一个通配符路由(或Vue3里的:pathMatch(.*)*
),放在路由规则最后(因为路由匹配是从上到下,先匹配先渲染):
Vue2版本:
{ path: '*', // 匹配所有未定义的路径 component: Error404 }
Vue3版本(因为Vue3的路由更严格,要写:pathMatch(.*)*
):
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: Error404 }
这样用户访问不存在的路由时,就会跳转到404页面。
避坑指南:这些配置细节新手常踩雷
路由跳转后,页面不更新是咋回事?
比如动态路由/product/:id
,从/product/1
跳到/product/2
,组件复用了,生命周期钩子不会重新触发,解决方法:
- 用组件内守卫
beforeRouteUpdate
,监听参数变化后重新请求数据; - 给
<router - view>
加key,强制组件重新渲染:<router - view :key="$route.fullPath"></router - view>
(但可能影响性能,谨慎用)。
路由传参用query还是params?有啥区别?
- params传参:参数在路由路径里(如
/product/1
),配置动态路由path: '/product/:id'
;刷新页面参数还在(因为在URL里),但如果路由没配动态段,params会丢失。 - query传参:参数在URL的查询字符串里(如
/product?id=1
),路由不用配动态段,跳转时to: { path: '/product', query: { id: 1 }}
;刷新页面参数还在,适合非必填、可选的参数。
简单说,想参数在URL里显示且刷新不丢,用query;想路径更干净(参数不在查询串),用params但要配动态路由。
嵌套路由的path为啥不能加斜杠?
嵌套路由的子路由path如果加,会变成根路径,比如父路由是/admin
,子路由path写/dashboard
,最终路径是/dashboard
,而不是/admin/dashboard
,所以子路由path要省略开头的,让它基于父路由路径拼接。
p标签结尾:“把vue - router配置拆成基础规则、场景方案、进阶优化这几块后,是不是清晰多了?其实核心就是「定义路由规则→注入Vue→用router - view和router - link渲染跳转」,再结合动态路由、嵌套、守卫这些功能,就能cover绝大多数项目场景,新手刚开始可以先把基础流程走通,再慢慢加场景化配置,碰到问题先看路由匹配顺序、参数传递方式这些细节,踩几次坑就熟啦~要是还有具体场景搞不定,评论区随时喊我分析~”
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。