Vue Router使用指南看这一篇就够了

您所在的位置:网站首页 app开发详解 Vue Router使用指南看这一篇就够了

Vue Router使用指南看这一篇就够了

2023-11-19 00:07| 来源: 网络整理| 查看: 265

介绍

Vue Router是Vue.js官方的路由管理器。它和 Vue.js 的核⼼深度集成,让构建单⻚⾯应⽤变得易如反掌。包含的功能有:

嵌套的路由/视图表

模块化的、基于组件的路由配置

路由参数、查询、通配符

基于 Vue.js 过渡系统的视图过渡效果

细粒度的导航控制

带有⾃动激活的 CSS class 的链接

HTML5 历史模式或 hash 模式,在 IE9 中⾃动降级

⾃定义的滚动条⾏为

起步

⽤ Vue.js + Vue Router 创建单⻚应⽤,是⾮常简单的。使⽤ Vue.js,我们已经可以通过组合组件来组成应⽤程序,当你要把 Vue Router添加进来,我们需要做的是,将组件 (components) 映射到路由(routes),然后告诉 Vue Router 在哪⾥渲染它们

安装

npm i vue-router -S

在main.js中

import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter)

推荐使用:vue add router 添加插件(记得提前提交)

基本使用

router.js

import Vue from 'vue' //1.导⼊ import Router from 'vue-router' import Home from './views/Home.vue' import About from './views/About.vue' //2.模块化机制 使⽤Router Vue.use(Router) //3.创建路由器对象 const router = new Router({ //mode: 'history', //history模式 干净的网页地址 没有#/之类的符号存在 routes:[{ path: '/home', component: Home }, { path: '/about', component: About }] }) export default router;

main.js

import Vue from 'vue' import App from './App.vue' import router from './router' Vue.config.productionTip = false new Vue({ // 4.挂载根实例 router, render: h => h(App) }).$mount('#app')

做好以上配置后

Home | About |

打开浏览器,切换Home和About超链接,查看效果

命名路由

在配置路由的时候,给路由添加名字,访问时就可以动态的根据名字来进行访问

const router = new Router({ routes:[{ path: '/home', name: 'home', component: Home }, { path: '/about', name:'about' component: About }] })

要链接到一个命名路由,可以给router-link的to属性传一个对象:

Home | About | 动态路由匹配

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有⼀个 User 组件,对于所有 ID 各不相同的⽤户,都要使⽤这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使⽤“动态路径参数”(dynamic segment) 来达到这个效果

User.vue

⽤户⻚⾯ export default { };

路由配置

const router = new Router({ routes:[{ path: '/user/:id', name: 'user', component: User, }] }) User |

查看效果

当匹配到路由时,参数值会被设置到this.$route.params,可以在每个组件中使用,于是,我们可以更新User的模板,输出当前用户的ID:

⽤户⻚⾯{{$route.params.id}}

响应路由参数的变化

提醒⼀下,当使⽤路由参数时,例如从 /user/1 导航到 /user/2,原来的组件实例会被复⽤。因为两个路由都渲染同个组件,⽐起销毁再创建,复⽤则显得更加⾼效。不过,这也意味着组件的⽣命周期钩⼦不会再被调⽤。

复⽤组件时,想对路由参数的变化作出响应的话,你可以简单地watch (监测变化) $route 对象:

/*使⽤watch(监测变化) $route对象 watch: { $route(to, from) { console.log(to.params.id); } }, */ // 或者使⽤导航守卫 beforeRouteUpdate(to,from,next){ //查看路由的变化 //⼀定要调⽤next,不然就会阻塞路由的变化 next(); } 404路由 const router = new Router({ routes:[ //.... // 匹配不到路由时,404⻚⾯显示 { path: '*', component: () => import('@/views/404') }] })

当使⽤通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: '*' } 通常⽤于客户端 404错误

当使⽤⼀个通配符时, $route.params 内会⾃动添加⼀个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

{ path: '/user-*', component: () => import('@/views/User-admin.vue') } this.$route.params.pathMatch // 'admin'

匹配优先级

有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。

查询参数

类似像地址上出现的这种:http://localhost:8080/page?id=1&title=foo

const router = new Router({ routes:[ //... { path: '/page', name: 'name', component:() => ('@/views/Page.vue') }] }) User

访问http://localhost:8080/page?id=1&title=foo查看Page

Page.vue

Page页面 {{$route.query.userId}} export default { created () { //查看路由信息对象 console.log(this.$route); }, } 路由重定向和别名

重定向

Example是从/重定向到/home:

const router = new Router({ mode: 'history', routes: [ // 重定向 { path: '/', redirect: '/home' }, { path: '/home', name: 'home', component: Home }, ] })

重定向的目标也可以是一个命名的路由:

const router = new VueRouter({ routes: [ { path:'/', redirect: {name: 'name'} } ] })

别名

{ path: 'user/:id', name: 'user', component: User, alias: '/alias' }

"别名"的功能让你可以自由地将UI结构映射到任意的URL,而不是受限于配置的嵌套路由结构。

路由组件传参

在组件中使⽤ $route 会使之与其对应路由形成⾼度耦合,从⽽使组件只能在某些特定的 URL 上使⽤,限制了其灵活性。

使⽤ props 将组件和路由解耦:

取代与$route的耦合

Index.js

{ path: '/user/:id', name: 'user', component: User, //props: true //props也可以是一个函数 props: (route) => { id: route.params.id, title: route.query.title } }

User.vue

⽤户⻚⾯{{$route.params.id}} ⽤户⻚⾯{{id}} export default{ //.... props: { id: { type: String, default: '' }, }, }

props也可以是个函数

User.vue

⽤户⻚⾯{{id}}-{{title}} export default { // ... props: { id: { type: String, default: '' }, title:{ type: String } }, }; 编程式导航

除了使用创建a标签来定义导航链接,我们还可以借助router的实例方法。通过编写代码来实现。

注意:在Vue实例内部,你可以通过router访问路由实例。因此你可以调用this.router访问路由实例。因此你可以调用this.router访问路由实例。因此你可以调用this.router.push。

声明式编程式router.push(...)

该⽅法的参数可以是⼀个字符串路径,或者⼀个描述地址的对象。例如:

//字符串 this.$router.push('home') //对象 this.$router.push({path: 'home'}) //命名的路由 this.$router.push({name: 'user', params: {userId}: '123'}) //带查询参数,变成 /register?plan=private this.$push({path: 'register', query:{plan: 'private'}})

前进后退

//在浏览器记录中前进一步,等同于history.forward() router.go(1) //后退一步记录,等同于history.back() router.go(-1) //前进3步记录 router.go(3) //如果history记录不够用,那就默认失败 router.go(-100) router.go(100) 嵌套路由 /user/1/profile /user/1/posts +------------------+ +-----------------+ | User | | User | | +--------------+ | | +-------------+ | | | Profile | | +------------> | | Posts | | || || || || | +--------------+ | | +-------------+ | +------------------+ +-----------------+

router.js

{ path: '/user/:id', name: 'user', component: User, props: ({params,query})=>({ id: params.id, title:query.title }), children:[ // 当 /user/:id/profile 匹配成功, // Profile 会被渲染在 User 的 中 { path:"profile", component: Profile }, // 当 /user/:id/posts 匹配成功, // Posts 会被渲染在 User 的 中 { path: "posts", component: Posts } ] }

在User组件的模板添加一个:

用户页面{{$route.params.id}} 用户页面{{id}}

App.vue

User/profile | User/posts | 命名视图

有时候想同时 (同级) 展示多个视图,⽽不是嵌套展示,例如创建⼀个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上⽤场了。

{ path: '/home', name: 'home', //注意这个key是components components: { default: Home, //默认的名字 main: ()=>import('@/views/Main.vue'), sidebar: ()=>import('@/views/Sidebar.vue') } }

App.vue

导航守卫

“导航”表示路由正在发生改变。

完整的导航解析流程

导航被触发。

在失活的组件里调用离开守卫。

调用全局的beforeEach守卫

在重用的组件里调用beforeRouterUpdate守卫(2.2+)。

在路由配置里调用beforeEnter。

解析异步路由组件。

在被激活的组件里调用beforeRouterEnter。

调用全局的beforeResolve守卫(2.5+)。

导航被确认。

调用全局的afterEach钩子。

触发DOM更新。

用创建好的实例调用beforeRouterEnter守卫中传给next的回调函数。

全局守卫

你可以使用router.beforeEach注册一个全局前置守卫

const router = new VueRouter({...}) router.beforeEach((to, form, next) => { //... })

有个需求,⽤户访问在浏览⽹站时,会访问很多组件,当⽤户跳转到 /notes ,发现⽤户没有登录,此时应该让⽤户登录才能查看,应该让⽤户跳转到登录⻚⾯,登录完成之后才可以查看我的笔记的内容,这个时候全局守卫起到了关键的作⽤。

有两个路由 /notes 和 /login。

router.vue

const router = new VueRouter({ routes: [ { path: '/notes', name: 'notes', component: () => import('@/views/Notes') }, { path: '/login', name: 'login', component: () => import('@/views/Login') }, ] }) //全局守卫 router.beforeEach((to, from, next) => { //用户访问的是'/notes' if(to.path === '/notes') { //查看一下用户是否保存了登录状态信息 let user = JSON.parse(localStorage.getItem('user')) if(user) { //如果有,直接放行 next(); }else { //如果没有,用户跳转登录页面登录 next('/login') } }else { next(); } })

Login.vue

提交 export default { data() { return { username: "", pwd: "" }; }, methods: { handleLogin() { //1.获取用户名和密码 //2.与后端发生交互 setTimeout(() => { let data = { username: this.username }; //保存用户登录信息 localStorage.setItem("user", JSON.stringfy(data)); //跳转我的笔记页面 this.$router.push({name: "notes"}); }, 1000); }, } }

App.vue

我的笔记 | 登录 | 退出 export default { methods: { handleLogout() { //删除登录状态信息 localStorage.removeItem("user"); //跳转到⾸⻚ this.$router.push('/') } }, } 组件内的守卫

你可以在路由组件内直接定义以下路由导航守卫:

beforeRouteEnter beforeRouteUpdate(2.2新增) beforeRouteLeave 用户编辑页面 import('@/views/Blog'), meta: { requiresAuth: true }, } { //路由独享的守卫 path: 'notes', name: 'notes', component: () => import('@/views/Notes'), meta: { requiresAuth: true } }, //全局守卫 router.beforeEach((to, from, next) => { if(to.matched.some(record => record.meta.requiresAuth)) { //需要权限 if(!localStorage.getItem('user')) { next({ path: '/login', query: { redirect: to.fullPath } }) }else { next(); } }else { next(); } })

Login.vue

//登录操作 handleLogin() { // 1.获取⽤户名和密码 // 2.与后端发⽣交互 setTimeout(() => { let data = { username: this.username }; localStorage.setItem("user", JSON.stringify(data)); // 跳转到之前的⻚⾯ this.$router.push({path:this.$route.query.redirect }); },1000}; } 数据获取

有时候,进⼊某个路由后,需要从服务器获取数据。例如,在渲染⽤户信息时,你需要从服务器获取⽤户的数据。我们可以通过两种⽅式来实现:

导航完成之后获取:先完成导航,然后在接下来的组件⽣命周期钩⼦中获取数据。在数据获取期间显示“加载中”之类的指示。

导航完成之前获取:导航完成前,在路由进⼊的守卫中获取数据,在数据获取成功后执⾏导航。

导航完成后获取数据

当你使⽤这种⽅式时,我们会⻢上导航和渲染组件,然后在组件的 created 钩⼦中获取数据。这让我们有机会在数据获取期间展示⼀个 loading 状态,还可以在不同视图间展示不同的 loading 状态。

Loading... {{ error }} {{ post.title }} {{ post.body }} export default { name: "Post", data() { return { loading: false, post: null, error: null }; }, // 组件创建完后获取数据, // 此时data已经被监视了 created() { // 如果路由有变化,会再次执⾏该⽅法 this.fetchData(); }, watch: { $route: "fetchData" }, methods: { fetchData() { this.error = this.post = null; this.loading = true; this.$http.get('/api/post').then((result) => { this.loading = false; this.post = result.data; }).catch((err) => { this.error = err.toString(); }); } }

扩展内容:

多页应用 MPA 每一个页面都是一个.html文件 SEO优化

单页应用 SPA 相当于一个a标签,切换不同的视图



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3