Vue Router【详解】含路由配置、路由定义、路由跳转、路由传参、自动注册路由、路由守卫、页面滚动、监听路由、$route、$router、路由过渡动画等

网友投稿 329 2022-09-22

Vue Router【详解】含路由配置、路由定义、路由跳转、路由传参、自动注册路由、路由守卫、页面滚动、监听路由、$route、$router、路由过渡动画等

Vue Router简介

Vue Router 官网  ​​Router 用于对vue项目中的路由进行管理,每个路由对应的页面,通过 进行渲染,可以配合 ​​​​​ 和 ​​​​ 使用。

Vue Router安装

npm install vue-router --save—dev

Vue Router配置

src/main.js 引入插件

// 插件-路由管理 vue-routerimport VueRouter from 'vue-router'Vue.use(VueRouter)import {routes} from "./routes";const router = new VueRouter({ routes})new Vue({ router, render: h => h(App),}).$mount('#app')

src/routes.js中定义路由(新建的文件)

export const routes = [ {path: '/', name: '首页',component: resolve => require(['@/page/index'], resolve)}, {path: '/dic',name: '速查手册', component: resolve => require(['@/projects/dic/index'], resolve)}, {path: '/404',component: resolve => require(['@/page/404.vue'], resolve),}, // 未匹配到的路由,重定向到 /404 {path: '*', redirect: '/404'},]

自动注册路由

page目录下的vue组件自动完成路由注册,路由为 /vue文件名

require.context('./page', true, /\.vue$/).keys().forEach(fileName => { let componentName = fileName.replace(/^\.\//, '').replace(/\.vue$/, ''); let temp = { path: '/' + componentName, component: resolve => require(["@/page/" + componentName], resolve) } routes.push(temp)});

路由模式 mode(通常用默认的hash模式)

浏览器时,默认为 hash 模式(url上有/#) —— 使用 URL 的 hash 来模拟一个完整的 URL,当 URL 改变时,页面不会重新加载。

Node.js 环境时,默认为abstract模式 —— 如果发现没有浏览器的 API,路由会自动强制进入这个模式。

可以改为 history 模式 ,但需要后端配合,详见 ​​router = new VueRouter({ // 不用mode: 'history'时,页面url地址后面会加上一个“#” // mode: 'history', routes})

路由基路径 base

默认值: ​​"/" ​​​,如果整个单页应用服务在 ​​/app/​​​ 下,然后 ​​base​​​ 就应该设为 ​​"/app/"​​

const router = new VueRouter({ base:'/app/', routes})

默认的激活的 class—— linkActiveClass

默认值: ​​"router-link-active"​​

默认的精确激活的 class —— linkExactActiveClass

默认值: ​​"router-link-exact-active"​​

页面滚动 scrollBehavior

通过scrollBehavior 方法可以控制路由跳转后页面的滚动行为,和最终滚动条的位置。

兼容性:只在支持 ​​history.pushState​​ 的浏览器中可用

const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { // return 期望滚动到哪个的位置 }})

​​scrollBehavior​​ 方法的参数

to —— 数据类型:路由 —— 即将进入的路由from —— 数据类型:路由 —— 即将离开的路由​​savedPosition ——​​​ 当且仅当​​popstate​​ 导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。

​​scrollBehavior​​ 方法的返回值 —— 滚动位置(数据类型:对象)

{ x: number, y: number }

{ selector: string, offset? : { x: number, y: number }}

滚动到顶部

scrollBehavior (to, from, savedPosition) { return { x: 0, y: 0 }}

保持原滚动条的位置

scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } }}

滚动到锚点

scrollBehavior (to, from, savedPosition) { if (to.hash) { return { selector: to.hash } }}

更高级的例子,参考 ​​返回一个 Promise 来得出预期的位置描述:scrollBehavior (to, from, savedPosition) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ x: 0, y: 0 }) }, 500) })}

平滑滚动

添加  behavior: 'smooth' 即可

scrollBehavior (to, from, savedPosition) { if (to.hash) { return { selector: to.hash, behavior: 'smooth', } }}

平滑滚动的兼容性参考  ​​path

路由定义得越早,优先级就越高。

{ // 会匹配所有路径 path: '*'}{ // 会匹配以 `/user-` 开头的任意路径 path: '/user-*'}

// "?" 可选参数{ path: '/optional-params/:foo?' },// "?" 可选路由{ path: '/optional-group/(foo/)?bar' }// 对参数添加正则校验(限制id必须为数字){ path: '/params-with-regex/:id(\\d+)' },

含有通配符的路由应该放在最后,路由 ​​{ path: '*' }​​ 通常用于客户端 404 错误。

{path: '/404',component: resolve => require(['@/page/404.vue'], resolve),},// 未匹配到的路由,重定向到 /404{path: '*', redirect: '/404'},

更多高级匹配方式,可以参考插件 ​​path-to-regexp​​​ 的官方文档  ​​2.6.0+ caseSensitive?: boolean, // 匹配规则是否大小写敏感?(默认值:false) pathToRegexpOptions?: Object // 编译正则的选项

路由命名 name

name属性为自定义的路由名称

推荐在路由跳转时,使用命名路由,这样即便path改变,也无需修改各页面中的path

{ path: '/user/:userId', name: 'user', component: User}

路由元信息 meta

通过meta可以为路由添加更多自定义的配置信息

{ path: 'bar', component: Bar, meta: { requiresAuth: true } }

路由重定向 redirect

当用户访问 ​​/a​​​时,URL 将会被替换成 ​​/b​​​,然后匹配路由为 ​​/b​​

{ path: '/a', redirect: '/b' }

{ path: '/redirect-with-params/:id', redirect: '/with-params/:id' },

{ path: '/a', redirect: { name: 'foo' }}

{ path: '/dynamic-redirect/:id?', redirect: to => { const { hash, params, query } = to if (query.to === 'foo') { return { path: '/foo', query: null } } if (hash === '#baz') { return { name: 'baz', hash: '' } } if (params.id) { return '/with-params/:id' } else { return '/bar' } } },

路由别名 alias

​​/a​​​ 的别名是 ​​/b​​​,意味着,当用户访问 ​​/b​​​ 时,URL 会保持为 ​​/b​​​,但是路由匹配则为 ​​/a​​​,就像用户访问 ​​/a​​ 一样。

{ path: '/home', component: Home, children: [ // 绝对路径 别名 { path: 'foo', component: Foo, alias: '/foo' }, // 相对路径 别名 (/home/bar-alias) { path: 'bar', component: Bar, alias: 'bar-alias' }, // 多个别名 —— 数组 { path: 'baz', component: Baz, alias: ['/baz', 'baz-alias'] }, // 默认别名 “” { path: 'default', component: Default, alias: '' }, // 嵌套路由的别名 /home/nested-alias/foo 会访问 /home/nested/foo) { path: 'nested', component: Nested, alias: 'nested-alias', children: [ { path: 'foo', component: NestedFoo } ] } ]}

路由懒加载

{ path:'./about', name:'About', component:() => import('../views/Aboout.vue')}

路由嵌套 children

{ path: '/user/:id', component: User, children: [ { // 当 /user/:id/profile 匹配成功, // UserProfile 会被渲染在 User 的 中 path: 'profile', component: UserProfile }, { // 当 /user/:id/posts 匹配成功 // UserPosts 会被渲染在 User 的 中 path: 'posts', component: UserPosts }, // 匹配其他子路由 { path: '', component: UserHome } ] }

动态路由 : (路由传参)

模式

匹配路径

$route.params

/user/:username

/user/evan

​{ username: 'evan' }​

/user/:username/post/:post_id

/user/evan/post/123

​{ username: 'evan', post_id: '123' }​

路由参数转为props传入组件

将组件和路由参数解耦,避免  $route.params 的使用,使组件在没有路由参数传入时,仍可正常复用。

方式一 布尔值

{ path: '/hello/:name', component: Hello, props: true }

访问 /hello/朝阳   相当于给组件传入props  { name:"朝阳"}

方式二 对象

{ path: '/static', component: Hello, props: { name: 'world' }}

访问 /static   就会向组件传入props  { name:"world"}

方式三 函数

尽可能保持 ​​props​​​ 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 ​​props​​,请使用包装组件,这样 Vue 才可以对状态变化做出反应。

{ path: '/search', component: SearchUser, props: route => ({ query: route.query.q })}

​​/search?q=vue​​​ 会将 ​​{query: 'vue'}​​​ 作为属性传递给 ​​SearchUser​​ 组件。

{ path: '/dynamic/:years', component: Hello, props: dynamicPropsFn }

function dynamicPropsFn (route) { const now = new Date() return { name: (now.getFullYear() + parseInt(route.params.years)) + '!' }}

响应路由参数的变化

路由不变,只改变路由参数时,如从 ​​/user/foo​​​ 导航到 ​​/user/bar​​,原来的组件实例会被复用,组件的生命周期钩子不会再被调用。

此时,需要监听路由的变化,或使用路由守卫。

按组打包

把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 ​​命名 chunk (opens new window)​​,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

监听路由的变化

watch: { $route(to, from) { // 对路由变化作出响应... } }

路由跳转 标签

User

​​to​​ 属性的使用方式与.push相同

当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。

相关属性

tag —— 默认 会渲染成带有正确链接的 标签,指定tag 属性可以改成其他标签

foo

  • foo
  • active-class —— 指定链接激活时的样式名,默认为"router-link-active"。(通过路由的构造选项 ​​linkActiveClass​​ 可以全局配置默认值)

    exact ——  使用“精确匹配模式”,避免模糊匹配上的路由都显示激活样式

    exact-active-class —— 链接被精确匹配时激活的 class

    .push

    会向 history 栈添加一个新的记录

    this.$router.push('/login')

    提供了 ​​path后​​,​​params​​ 会被忽略

    // 字符串 —— 没有/时会自动加/router.push('home')等同于router.push('/home')// 对象router.push({ path: 'home' })// 命名的路由router.push({ name: 'user', params: { userId: '123' }})// 带查询参数,变成 /register?plan=privaterouter.push({ path: 'register', query: { plan: 'private' }})

    const userId = '123'router.push({ name: 'user', params: { userId }}) // -> /user/123router.push({ path: `/user/${userId}` }) // -> /user/123

    第二个可选参数——回调函数onComplete——导航成功完成时调用 (在所有的异步钩子被解析之后)

    控制台报错提示跳转到重复路由时,可以将第二个可选参数设为空的箭头函数来解决。

    this.$router.push('/login',()=>{})

    第三个可选参数——回调函数onAbort——导航终止时调用 (导航到相同的路由、或在当前导航完成之前导航到另一个不同的路由)

    .replace

    不会向 history 栈添加新的记录,参数规则与.push相同

    this.$router.replace('/login')

    .go

    参数是一个整数,用于history 记录中向前或者后退多少步,类似 ​​window.history.go(n)​​。

    // 在浏览器记录中前进一步,等同于 history.forward()router.go(1)// 后退一步记录,等同于 history.back()router.go(-1)// 前进 3 步记录router.go(3)// 如果 history 记录不够用,则失败,不会跳转router.go(-100)

    .back()

    后退——跳转到上一路由(若浏览器存在history 记录)

    router.back()

    .forward()

    前进——跳转到下一路由(若浏览器存在history 记录)

    router.forward()

    路由跳转——实战范例

    // 返回到上一页面 goBack() { window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/')}

    当前路由 this.$route

    $route为当前路由对象,用于获取当前路径,路由中的动态片段,路径中的查询参数等信息

    $route.path— 字符串 —当前路由的绝对路径,定义路由时的path值,如"/foo/bar"$route.fullPath— 字符串 —当前路由的完整路径,含查询参数和 hash ,如"​​/stock?name=朝阳#hello​​"$route.query —对象——当前路由中查询参数的键值对

    在路由“ ​​/test/1​​​​?name=朝阳 ​​​”​​中,​​$route.query的值为 { "name": "朝阳" }

    $route.name— 字符串 —当前路由的名称,如“测试”

    {name:'测试', path: '/test/:id', component: resolve => require(['@/components/test/index'], resolve)},

    $route.params —对象 —— 当前路由中动态片段的键值对

    {path: '/test/:id', component: resolve => require(['@/components/test/index'], resolve)},

    在路由 ​​/test/1​​ 中,$route.params的值为 { "id": "1" }

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

    // 给出一个路由 { path: '/user-*' }this.$router.push('/user-admin')this.$route.params.pathMatch // 'admin'// 给出一个路由 { path: '*' }this.$router.push('/non-existing')this.$route.params.pathMatch // '/non-existing'

    $route.hash — 字符串 — 当前路由的hash值,如​​—— 字符串 —— 重定向来源的路由的名字(如果存在重定向),如由name为a的路由,重定向到name为b的路由,则$route.redirectedFrom值为a$route.matched — 数组 — 路由匹配到的所有已定义的路由会存入 $route.matched 数组中,包含定义路由时的嵌套路由数组children

    使用范例:在全局导航守卫中检查元字段

    router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { // this route requires auth, check if logged in // if not, redirect to login page. if (!auth.loggedIn()) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } } else { next() // 确保一定要调用 next() }})

    路由器 this.$router

    $router 对象是全局路由的实例,用于实现路由的跳转,有以下属性:

    app ——  路由对应的vue实例mode ——  路由模式currentRoute —— 当前路由对象,即 $route

    使用 this.$router 进行路由跳转的范例

    this.$router.push({name:'测试',params:{id:1}}); //会向 history 栈添加一个新的记录

    跳转到名称为测试,动态片段为1的页面,即​​/test/1​​

    this.$router.push({path:'/test/1',query:{name:'朝阳'}}); //会向 history 栈添加一个新的记录

    跳转到路径为/test/1,查询参数为name=朝阳,即“ ​​/test/1​​​​?name=朝阳 ​​”

    this.$router.go(-1); // 回到上一页

    this.$router.replace('/'); // 使用 / 路由对应的页面,替换当前页面,不会向 history 栈添加一个新的记录

    同时展示多个视图(命名视图)

    如果 ​​router-view​​​ 没有设置名字,那么默认为 ​​default​​

    { path: '/', components: { default: Foo, a: Bar, b: Baz } }

    路由过渡动画

    全局路由动画

    局部路由动画

    在指定路由的组件外,加上

    动态路由动画

    // 父组件内 _ 根据路由层级决定过渡动画为左滑/右滑watch: { '$route' (to, from) { const toDepth = to.path.split('/').length const fromDepth = from.path.split('/').length this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' }}

    版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

    上一篇:vue全屏滚动——vue-fullpage.js教程
    下一篇:休克文案:品牌开始对麻将下手了!
    相关文章

     发表评论

    暂时没有评论,来抢沙发吧~