关于vue-router可能需要注意到的事项

现在的前端框架都会配备一个路由框架,vue有vue-router,react有react-router,angular也有angular-route,当然还有一些优秀插件来完善这些router的做更多的事情

安装

npm i vue-router -S

基本使用

import Vue from './view-global';
import VueRouter from 'vue-router'
import App from './micro/app.vue'

import Home from './micro/home'
import Login from './micro/login'
import About from './micro/about'
import User from './micro/user'
const router = new VueRouter({
    mode: 'hash',
    routes: [
        { path: '/home', name: 'Home', component: Home, meta: { title: "主页" } },
        { path: '/login', name: 'Login', component: Login, meta: { title: "登录" } },
        { path: '/about', name: 'About', component: About, meta: { title: "关于" } },
        { path: '/user', name: 'User', component: User, meta: { title: "用户" } }
    ]
})
Vue.use(VueRouter)
new Vue({
    router,
    render: h => h(App),
}).$mount('#app')
// app.vue

router-link-active

vueRouter 会自动添加这个类,当点击Home和Login来回切换时,发现html结构,a 标签有一个样式类 .router-link-active 也在来回切换, 原来这是当router-link 处于选中状态时,因此我们也可以利用这个类来改变选中时的状态,如选中时,让它变成红色,字体放大,如果未选中的也可在 router-link 直接给它添加一个 class就可以了,比如自定义一个default-styles

router-link

属性有 to 、replace、 append、 tag、 active-class、 exact 、 event、 exact-active-class

to(必选参数):类型string/location
//字符串形式
Home
//动态绑定 v-bind
Home
Home
User
// 带参数 参数在url 获取参数 this.$route.query
query带参数
// 带参数 获取参数 this.$route.params
params带参数
tag 类型string,默认值a
// 如果想要  渲染成某种标签,例如 
  • Home // 如果此时我们想要在这个li标签中添加a标签,如下所示,可以不为a标签添加href属性即可哦 User
  • 可以看渲染结果,在这种情况下, 将作为真实的链接 (它会获得正确的 href 的),而 "激活时的CSS类名" 则设置到外层的 li,看下方图片渲染结果:
    image.png

    active-class : 类型 string默认值:router-link-active
    // 修改激活选中的class类名
    带参数
    // 全局修改
    const router = new VueRouter({
        mode: 'hash',
        linkActiveClass: 'activeClass', // 全局配置
        routes: [
            { path: '/home', name: 'Home', component: Home, meta: { title: "主页" } },
            { path: '/login', name: 'Login', component: Login, meta: { title: "登录" } },
            { path: '/about', name: 'About', component: About, meta: { title: "关于" } },
            { path: '/user', name: 'User', component: User, meta: { title: "用户" } }
        ]
    })

    image.png

    exact-active-class 类型 string 默认值:router-link-exact-active

    配置当链接被精确匹配的时候应该激活的 class。注意默认值也是可以通过路由构造函数选项 linkExactActiveClass 进行全局配置的,看起来有点模糊,举个栗子,例如:

    
    // 当用户访问 /article/1 时会被激活为
    
    
    // 修改一下
    
    
    // 当用户访问 /article/1 时会被激活为,不会激活这个link的class
    

    router-link 默认情况下的路由是模糊匹配

    exact 类型 boolean 默认值:false

    "是否激活" 默认类名的依据是 inclusive match (全包含匹配), 举个例子

     
  • 全局匹配
  • exact严格匹配
  • 简单点说,第一个的话,如果地址是/a,或/a/b,……都会匹配成功,
    但加上exact,只有当地址是/时被匹配,其他都不会匹配成功

    event 类型: string | Array 默认值: click
    article

    如果我们不加event,那么默认情况下是当我们点击article的时候,跳转到相应的页面,但当我们加上event的时候,就可以改变触发导航的事件,比如鼠标移入事件

    replace 类型: boolean 默认值: false

    设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录
    push replace go 之间的区别

    router.push() :导航跑到不同的URL,这个方法会向history栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的url
    router.replace(): 跟router.push作用是一样的,但是,它不会向history添加新记录,而是跟它的方法名一样替换掉当前的history记录
    router.go(n): 这个方法的参数是一个整数,意思是在history记录中向前或者后退多少步,类似window.history.Go(n)
    append 类型: boolean 默认值: false

    设置 append 属性后,则在当前 (相对) 路径前添加基路径

    Home

    设置append属性后,则在当前路径前添加基路径,例如,我们从/a导航到一个相对路径b,如果没有配置append,则路径为/b,如果配了,则为/a/b

    快速设置title

    Router.beforeEach((to,from,next) => {
        window.document.title= to.meta.title
    })

    滚动行为

    使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动

    // 2.8.0 新增
    const router = new VueRouter({
        scrollBehavior (to, from, savedPosition) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve({ x: 0, y: 0 })
                }, 500)
            })
        }        
    })

    利用路由元信息更细颗粒度地控制滚动,可以查看github官方列子

    路由懒加载

    官方描述:当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了

    加载方式

    非按需加载
    { path: '/user', name: 'User', component:require(['./micro/user'], resolve), meta: { title: "用户" } }
    按需加载
    { path: '/user', name: 'User', component: (resolve) => require(['./micro/user'], resolve), meta: { title: "用户" } }
    // 或者使用webpack的require.ensure技术
    { path: '/user', name: 'User', component: resolve => require.ensure([], () => resolve(require('./micro/user')), 'user'), meta: { title: "用户" } }

    按需加载会在页面第一次请求的时候,把相关路由组件块的js添加上;非按需加载则会把所有的路由组件块的js包打在一起。
    当业务包很大的时候建议用路由的按需加载(懒加载),可以看我网站,打开控制台,当点击左侧菜单,会发现加载相对应的js包

    关于vue-router可能需要注意到的事项_第1张图片

    require.ensure 参数解释
    第一个参数的依赖关系是一个数组,代表了当前需要进来的模块的一些依赖
    第二个参数回调就是一个回调函数其中需要注意的是,这个回调函数有一个参数要求,通过这个要求就可以在回调函数内动态引入其他模块值得注意的是,虽然这个要求是回调函数的参数,理论上可以换其他名称,但是实际上是不能换的,否则的的的的WebPack就无法静态分析的时候处理它
    第三个参数errorCallback比较好理解,就是处理错误的回调
    第四个参数chunkName则是指定打包的组块名称

    异步组件

    // setTimeout 演示ajax
    const User= Vue.component('later', function (resolve) {
        setTimeout(function () {
            require(['./user.vue'], resolve)
        }, 3000);
    });
    components: {
       User
    },

    注意异步组件页面渲染的时候会跳动,使用下方高级异步组件,解决体验问题

    // 更高级的异步组件
    const AsyncComponent = () => ({
      // 需要加载的组件 (应该是一个 `Promise` 对象)
      component: import('./MyComponent.vue'),
      // 异步组件加载时使用的组件
      loading: LoadingComponent,
      // 加载失败时使用的组件
      error: ErrorComponent,
      // 展示加载时组件的延时时间。默认值是 200 (毫秒)
      delay: 200,
      // 如果提供了超时时间且组件加载也超时了,
      // 则使用加载失败时使用的组件。默认值是:`Infinity`
      timeout: 3000
    })

    hash模式和history模式

    hash模式:

    在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取; 特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 https://www.vipbic.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误

    简单实现hash

    
    

    history模式:

    history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。 history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

    简单实现history

    
    

    vue-router导航守卫的类型

    1、全局守卫
    2、路由独享守卫
    3、路由组件内的守卫

    全局守卫

    vue-router全局有三个守卫
    router.beforeEach 全局前置守卫 进入路由之前
    router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用
    router.afterEach 全局后置钩子 进入路由之后
    全局导航守卫的执行顺序

    例如从 /Home 页面跳转到 /User,全局导航守卫执行顺序大概是这样的

    router.beforeEach((to, from, next) => {
        console.log('全局前置守卫: beforeEach')
        next()
    })
    router.beforeResolve((to, from, next) => {
        console.log('全局解析守卫: beforeResolve')
        next()
    })
    router.afterEach((to, from) => {
        console.log('全局后置钩子: afterEach')
    })

    image.png

    路由组件内守卫

    beforeRouteEnter 进入路由前, 在路由独享守卫后调用 不能 获取组件实例 this,组件实例还没被创建
    beforeRouteUpdate (2.2) 路由复用同一个组件时, 在当前路由改变,但是该组件被复用时调用 可以访问组件实例 this
    beforeRouteLeave 离开当前路由时, 导航离开该组件的对应路由时调用,可以访问组件实例 this
    beforeRouteEnter(to, from, next) {
        console.log('进入前:beforeRouteEnter')
        next()
    },
    beforeRouteUpdate(to, from, next) {
        console.log('路由改变时:beforeRouteUpdate') // 比如user/123,切到user/456,才会触发
        next()
    },
    beforeRouteLeave(to, from, next) {
        console.log('离开前:beforeRouteLeave')
        next()
    }
    路由组件内守卫的执行顺序

    例如从 /Home 页面跳转到 /User 然后在跳到Home,执行顺序大概是这样的

    关于vue-router可能需要注意到的事项_第2张图片

    当我点击User时回调用路由组件内守卫的beforeRouteEnter,然后当我点击About时,会调用beforeRouteLeave

    beforeRouteEnter

    也可以先获取数据,等数据获取出来才真正的显示页面。
    需要注意:这里是拿不到组件this,因为没有通过next之前,组件没有被创建,所以用this === undefined ,不能调用上的任何东西

    beforeRouteUpdate注意点

    对于user/123,切到user/456 这样的路由页面,一般在mounted获取数据,第二次进来的时候,不会被触发(数据不会更新),所以数据的初始化获取不要用mounted,最好使用beforeRouteUpdate,或者使用watch,watch相对比较麻烦,而且不能控制路由跳转的行为

    beforeRouteLeave

    beforeRouteLeave:可以用来表单填写成功,是否保存提示等

    导航路由独享守卫

    const router = new VueRouter({
        mode: 'history',
        routes: [
          {
            path: '/user',
            component: User,
            beforeEnter: function guardRoute(to, from, next) {
        // 参数用法什么的都一样,调用顺序在全局前置守卫后面,所以不会被全局守卫覆盖
              console.log('导航路由独享守卫:beforeEnter')
              next()
            }
          }
        ]
    })

    总结路由执行顺序

    比如从User组件跳转到About组件所执行的顺序

    关于vue-router可能需要注意到的事项_第3张图片

    1、beforeRouteLeave //路由组件内守卫
    2、beforeEach // 全局前置守卫-路由进入开始
    3、beforeEnter // 导航路由独享守卫
    4、beforeRouteEnter // 路由组件内前置守卫
    5、beforeResolve //全局解析守卫
    6、afterEach // 全局后置钩子

    更多关于vue-route

    动态组件 & 异步组件
    滚动行为
    导航守卫实践与解析

    关于我

    关于vue-router可能需要注意到的事项_第4张图片

    你可能感兴趣的:(前端,vue-router,vue.js)