关于vue.js:vueVueRouter路由管理

4次阅读

共计 8341 个字符,预计需要花费 21 分钟才能阅读完成。

Vue-Router 路由治理

  1. 根底应用
  2. 进阶

1 根底

  1. 装置与根本应用
  2. 动静路由
  3. 嵌套路由
  4. 编程式导航
  5. 命名路由
  6. 命名视图
  7. 重定向和别名
  8. 路由组件传参
  9. History 模式
  10. Modules

1.1 装置与根本应用

// 装置
npm install vue-router --save
//main.js 内引入
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// 此时在 vue 实例上会多出 `$route` 和 `$router` 两个属性

创立两个页面

//About.vue
<template>
  <div> 对于页面 </div>
</template>
//Detail.vue
<template>
  <div> 对于页面 </div>
</template>

配置路由

//router.js 文件
import VueRouter from "vue-router";
import About from './pages/About'
import Detail from './pages/Detail'

export const router = new VueRouter({
    routes: [
        {
            path: '/about',
            component: About,
        },
        {
            path: '/detail',
            component: Detail
        }
    ]
})
  • 引入 VueRouter 并实例化,引入组件
  • 配置对象的 routes 选项,以 数组 - 对象 模式 注册路由,包含门路与组件

在 mian.js 中引入 router 实例并注册

//mian.js
import {router} from './router'

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')
// 此时能够察看到 $router 与 $route 的相干配置

在 App.vue 中应用路由

<template>
  <div id="app">
    <router-link to="/about"> 跳转 about</router-link><br />
    <router-link to="/detail"> 跳转 detail</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {name: "App",};
</script>

router-link为路由 入口 ,在 to 中配置门路
router-view 为路由 进口 ,跳转的页面在此处显示
相似于 动静组件 ,实现了根本的跳转性能,路由的性能更加弱小
$router 相似于 $store,在根实例注册后, 子组件 都能够拜访到原 路由实例,不须要频繁的在子组件中引入。$route 是以后路由

1.2 动静路由

依据不同的门路参数跳转至同一组件,显示不同的数据

//router.js
{
    path: '/about:id',
    component: About,
},
//App.vue
<template>
  <div id="app">
    <router-link to="/about/:'1'"> 用户 1 </router-link><br />
    <button @click="to"> 用户 2 </button>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {to() {this.$router.push('/about/:"2"');
    },
  },
};
</script>
//About.vue
<template>
  <div> 对于页面{{userId}}</div>
</template>

<script>
export default {
  computed: {userId() {return this.$route.params.id;},
  },
};
</script>
  • 在 router 中注册的门路增加:param
  • 跳转时能够应用 router-link 或者应用 $router.push,门路中携带参数
  • 在跳转至的路由能够通过 $route.params 拜访动静门路的参数

    能够依据参数去申请数据再渲染页面

  • :,对应定义的是 params 参数
  • ? = &,能够定义 query 参数,通过 $route.query 拜访

    <router-link to="/about/?id=1"> 用户 1 </router-link><br />

通配符
捕捉所有路由或 404 Not found 路由

{    // 匹配所有门路
    path:'*'
}
{    // 匹配以 '/user' 结尾的任意门路
    path:'/user-*'
}

应用通配符路由时,$route.params 会增加一个名为 pathMatch 参数。蕴含 URL 通配符匹配的局部

//router.js
{
    path: '*',
    component: () => import('./pages/Notfound')
}

当跳转的门路匹配失败时,能够匹配通配符门路,并通过 pathMatch 参数提醒谬误的门路
应用 ’/user-*’,能够设置特定门路下某种页面未找到的提示信息

1.3 嵌套路由

有时在路由跳转后可能还须要路由跳转,这时就须要嵌套多级路由
在路由注册时增加 children 属性

//router.js
{
    path: '/about',
    component: About,
    children: [
        {
            path: 'child',
            component: () => import('./pages/Child')
        }
    ]
},
// 跳转
<router-link to="/about/child"> 二级跳转 </router-link>

子路由的门路前不须要/,不然会认为从跟门路开始

1.4 编程式导航

除了应用 router-link申明式 创立 a 标签的形式进行跳转,也能够是借助 router 的实例办法 编程式 实现跳转
push:向 history 栈 增加 一个新的记录,能够点击浏览器的后退至之前的 URL
replace替换 以后的 history 栈顶记录
go(n):后退或后退 |n| 步,正数为后退,负数为后退,记录不够用则失败

this.$router.push({
  path: "/detail",
  // params: {userId: 123},
  query: {user: "张三"},
});

push 中的数据能够应用 对象模式 ,params 参数 不能 与 path同时应用 ,router-link 中的to 也反对对象模式的写法
能够应用 name 属性传递 params 参数

  • params参数:必须 门路 上增加参数名,并且跳转时应用 name 属性
  • query参数:不用在注册时在 门路 上增加信息,跳转时应用 path 或 name 都可

    当在门路中增加了参数,然而跳转时没有传递 params 参数,也会跳转失败
    应用 name 属性时,反对同时传递 params 与 query 参数

1.5 命名路由

上述曾经对 name 进行了一些介绍,是对路由的命名
能够简化门路过长的问题,同时防止 params 参数的问题

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

1.6 命名视图

router-view 中能够增加 name 属性,对应路由中的组件
注册路由时的 components 能够是对象模式,蕴含多个组件,key 提供给 name 抉择

//router.js
{
    name: 'detail',
    path: '/detail/:userId',
    components: {
        default: Detail,
        a: () => import('./pages/Ads')
    }
},
// 视图
<router-view></router-view>
<router-view name="a"></router-view>

没有 name 属性的视图,应用 default 的组件

1.7 重定向和别名

重定向
拜访 ’/a’ 重定向 ’/b’,URL 与匹配的路由都换成 ’/b’

// 门路
routes: [{ path: '/a', redirect: '/b'}
]
// 命名
routes: [{ path: '/a', redirect: { name: 'foo'}}
]
// 动静办法
routes: [
  { path: '/a', redirect: to => {
    // 办法接管 指标路由 作为参数
    // return 重定向的 字符串门路 / 门路对象
  }}
]

能够在返回主页时将根门路重定向为子路由门路,保障页面的填充

别名
‘/a’ 的别名 ’b’,当拜访 ’/b’ 时,URL 依然是 ’/b’,然而路由匹配为 ’/a’,相当于拜访 ’/a’,只是名字不同

routes: [{ path: '/a', component: A, alias: '/b'}
]

能够自在地将 UI 构造映射到任意的 URL,不受限与配置的嵌套的路由构造

1.8 路由组件传参

props属性:boolean|Object|Function
$route 会使组件与对应路由高耦合,导致组件只能在特定的 URL 上应用,限度灵活性。
应用 props 属性能够将组件和路由 解耦

// 对象模式
{
    name:'detail',
    path:'/detail',
    component:Detail,
    props:{foo:'a',bar:'b'}
}

在 Detail组件中 ,能够间接在props 中申明 后应用
对象模式传递的是静态数据,在配置的时候就写好的,应用场景较少

// 布尔模式
{
    ...
    props:true,
}
// 多组件
{
    ...
    components:{Detial,Ads},
    props:{Detail:true,Ads:false}
}

将路由跳转时的 params 参数传入组件中,在组件的 props 中申明后应用

// 函数模式
{
    ...
    props($route){
        return {
            id:$route.params.userId,
            name:$route.query.user
        }
    }
}
// 解构赋值简写 - 相似于 vuex 的 action 中的 context 对象
{
    ...
    props({params,query}){
        return {
            id:params.userId,
            name:query.user
        }
    }
}

在不应用 props 的状况下,传递的参数全副都在 URL 上,须要应用计算属性一一获取
应用 props 的函数模式,能够将 params 和 query 参数以及静态数据在组件中的 props 中申明
这样简化了取值的操作,解耦合

1.9 History 模式

router 中的配置除了 routes 选项外,还要其余选项,例如 mode
mode 默认为 hash,地址栏会有一个# 号,URL 扭转时,页面不会从新加载
更改为失常的网址模式,应用 mode:'history'
history 模式须要肯定的 后盾反对,不然会呈现 404

这是因为 hash 模式下 #后的地址作为路由跳转,不会发动 http 申请,然而在 history 模式下,刷新页面时,会发动 http 申请,因为没有# 的分隔会将整个地址都作为申请地址
nginx

location / {try_files $uri $uri/ /index.html;}

Node.js

const http = require('http')
const fs = require('fs')
cosnt httpPort = 80

http.createServer((req,res)=>{fs.readFile('index.html','utf-8',(err,content)=>{if(err){...}
        res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'})
        
        res.end(content)
    })
}).listen(httpPort,()=>{console.log('Server listening on:http://loaclhost:%s',httpPort)
})

能够在 Node.js 中应用 connect-history-api-fallback 插件,疾速解决 history 模式后端地址和前端路由地址的抵触,造成申请失败

2.10 Modules

当嵌套路由的层级过多时,能够将其宰割成多个模块
与 vuex 拆分的形式相似,不必创立 module 数组,引入后间接在 routes 数组中注册即可

//routers 文件夹中的 index.js 入口文件
import VueRouter from 'vue-router'
import {about} from './modules/about'
import {detail} from './modules/detail'
import {Notfound} from './Notfound'

export const router = new VueRouter({
    routes: [{ path: '/'},
        about,
        detail,
        Notfound
    ]
})

批改为模块化后须要从新在 main.js 中引入并注册

2 进阶

  1. 路由守卫
  2. 路由元信息
  3. 过渡动效
  4. 数据获取
  5. 滚动行为
  6. 路由懒加载
  7. 导航故障

2.1 路由守卫

  1. 全局前置守卫
  2. 全局解析守卫
  3. 全局后置钩子
  4. 路由独享守卫
  5. 组件内的守卫
  6. 整体流程

2.1.1 全局前置守卫

beforeEach

const router = new VueRouter({})
router.beforeEach((to,from,next)=>{})
  • to : 指标路由
  • from : 来到的路由
  • next : 放行函数,无参数 间接跳转至指标路由

    • next(false) 中断以后导航
    • next(‘/’)或 next({path:’/’}) 指定路由跳转,能够应用 name 以及其余选项
    • next(error) 中断以后导航,并将 Error 实例传入 router.onError()执行回调
    • next 函数仅能被调用一次
//index.js - 模仿未登录用户拜访页面,重定向至登录页面
router.beforeEach((to, from, next) => {if (to.name !== 'login' && to.name !== 'register' && !isAuthenticated) {next({ name: 'login'})
    } else {next()
    }
})

如果跳转应用的 push 的形式,被守卫拦挡重定向后会报错,但不影响应用
能够在 push 后应用 catch 捕捉谬误

2.1.2 全局解析守卫

beforeResolve
相似于 beforeEach
区别:在导航被确认之前,同时在所有 组件内守卫 异步路由组件 被解析之后,解析守卫被调用

2.1.3 全局后置钩子

afterEach
与守卫不同的是没有 next 放行函数

router.afterEach((to, from) => {// ...})

2.1.4 路由独享守卫

beforeEnter
与全局不同的在于它作为一个路由的配置项,独自管制一个路由

routes: [
  {
    path: '/foo',
    component: Foo,
    beforeEnter: (to, from, next) => {// ...}
  }
]

to : 跳转至以后路由
from : 由某路由跳转来

能够限度 from 能够从何处跳转至该路由

2.1.5 组件内的守卫

在组件中作为配置 选项
beforeRouteEnter:相似于独享守卫,在组件实例创立前调用,故不能获取 vm 实例

能够在 next 中增加回调函数拜访组件实例

beforeRouteEnter (to, from, next) {
  next(vm => {// 通过 `vm` 拜访组件实例})
}

beforeRouteUpdate:门路扭转,组件被复用时调用,能够拜访 vm 实例

此时的 this 代表的时 from 的路由组件实例

beforeRouteLeave:来到该组件的对应路由时调用,能够拜访该组件 vm 实例

能够在来到前对组件中的内容进行判断,确认是否来到

2.1.6 整体流程

2.2 路由元信息

meta 配置项,存储路由元信息
在间断的路由嵌套中,每一层的路由信息都会被收集到 $route.matched数组
能够应用数组的遍历办法遍历 matched 数组对 meta 字段进行查看

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()}
})

2.3 过渡动效

router-view 是根本的动静组件,相当于 component 标签
所以能够应用 transition 标签对其进行包裹实现 过渡 成果
同样的应用 keep-alive 实现组件 缓存
transition 与 keep-alive

2.4 数据获取

在路由跳转时常常会随同着从服务器获取数据
导航实现后申请:实现导航后,在组件的申明周期钩子中申请数据。申请实现期间显示 ” 加载 ” 提醒。

应用 v -if 条件渲染加载页面、谬误页面以及申请胜利页面
在 created 钩子中申请数据

导航实现前申请:在路由守卫中获取数据,获取胜利后执行导航

beforeRouteEnter 中申请数据,在 next()回调 中配置申请取得的数据

2.5 滚动行为

scrollBehavior 配置选项
切换至新路由时,页面滚动到顶部或者放弃原先的滚动地位

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

默认状况下不产生滚动,返回 svaedPosition 时后退 / 后退与浏览器原生操作统一

return {x:0,y:0}

依据坐标间接滚动

meta:{x:0,y:0}
return {
    selector:to.meta,
    behavior:'smooth'
}

依据元信息进行 平滑滚动

return new Promise((resolve, reject) => {setTimeout(() => {resolve({ x: 0, y: 0})
  }, 500)
})

能够返回一个 Promise,resolve 中传入滚动信息,实现 异步滚动

2.6 路由懒加载

异步组件

// 异步组件工厂函数
const AsyncComponent = (url) => ({// 须要加载的组件 (应该是一个 `Promise` 对象)
  component: import(url),
  // 异步组件加载时应用的组件
  loading: LoadingComponent,
  // 加载失败时应用的组件
  error: ErrorComponent,
  // 展现加载时组件的延时工夫。默认值是 200 (毫秒)
  delay: 200,
  // 如果提供了超时工夫且组件加载也超时了,// 则应用加载失败时应用的组件。默认值是:`Infinity`
  timeout: 3000
})

应用 import()函数异步引入组件,能够在首次渲染时先不下载局部组件
在拜访异步组件时再进行下载

2.7 导航故障

在路由导航失败时能够在 push 后链式处理错误信息

  • isNavigationFailure(failure,NavigationFailureType)
  • NavigationFailureType

    • redirected: 调用了 next(newLocation) 重定向到了其余中央
    • aborted: 调用了 next(false) 中断了本次导航
    • cancelled: 以后导航还没有实现之前又有了一个新的导航
    • duplicated: 导航被阻止,因为咱们曾经在指标地位了
import VueRouter from 'vue-router'
const {isNavigationFailure, NavigationFailureType} = VueRouter

// 正在尝试拜访 admin 页面
router.push('/admin').catch(failure => {if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
    // 向用户显示一个小告诉
    showToast('Login in order to access the admin panel')
  }
})
// 正在尝试拜访 admin 页面
router.push('/admin').catch(failure => {if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
    failure.to.path // '/admin'
    failure.from.path // '/'
  }
})
正文完
 0