Vue-Router

原理

vue-router的原理就是通过对URL地址变化的监听,继而对不同的组件进行渲染

HTML5 History 模式

vue-router 默认 hash 模式 —— 使用 URLhash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。 history 模式需要后台配置支持(配置Nginx)。如果后台没有正确的配置,当用户在浏览器直接访问url就会返回 404

  • hash
    • 原理是onhashchage事件,可以在window对象上监听这个事件
    window.onhashchange = function (event) {
        console.log(event.oldURL, event.newURL)
        let hash = location.hash.slice(1)
    }
    
  • history
location / {
    try_files  $uri $uri/ @router index index.html;
}
location @router {
    rewrite ^.*$ /index.html last;
}

$route和$router的区别

  • $route 是路由信息对象,包括pathparamshashqueryfullPathmatchedname 等路由信息参数。
  • $router 是路由实例对象,包括了路由的跳转方法,钩子函数等

路由懒加载

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

把组件按组分块

const Foo = () => import(/* webpackChunkName: "foo" */ './Foo.vue') //foo[hash].js
const Bar = () => import(/* webpackChunkName: "bar" */ './Bar.vue') //bar[hasg].js

Vue-Router钩子函数

首页可以控制导航跳转,beforeEachafterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。

  • beforeEach主要有3个参数tofromnext
  • toroute即将进入的目标路由对象。
  • fromroute当前导航正要离开的路由。
  • nextfunction一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转

路由跳转

  1. <router-link :to="...">
  2. 编程式:router.push(...)

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

// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 pathparams 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path:

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

params和query的区别

  • query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.namethis.$route.params.name
  • url地址显示:query更加类似于我们ajaxget传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示

注意点:query刷新不会丢失query里面的数据,params刷新会丢失params里面的数据。

怎么重定向页面

const router = new VueRouter({
    routes: [
        { path: '/a', redirect: '/b' },
        { path: '/a', redirect: { name: 'b' }},
        { 
            path: '/a', 
            redirect: to =>{
                const { hash, params, query } = to
                if (query.to === 'foo') {
                    return { path: '/foo', query: null }
                }else{
                   return '/b' 
                }
            }
            
        }
    ]
})

怎么配置404页面

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

切换路由时,需要保存草稿的功能,怎么实现呢

<keep-alive :include="include">
    <router-view></router-view>
 </keep-alive>

其中include可以是个数组,数组内容为**路由的name**选项的值

路由导航守卫和Vue实例生命周期钩子函数的执行顺序

路由导航守卫都是在Vue实例生命周期钩子函数之前执行的

在afterEach钩子中可以使用next()吗

不可以,不接受next的参数

在beforeRouteEnter导航守卫中可以用this吗

不可以,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建

可以通过传一个回调给next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数

beforeRouteEnter(to, from, next) {
    next(vm => {
        console.log(vm)
    })
}

怎么在组件中监听路由参数的变化

有两种方法可以监听路由参数的变化,但是只能用在包含<router-view />的组件内

watch: {
    '$route'(to, from) {
        //这里监听
    },
},
beforeRouteUpdate (to, from, next) {
    //这里监听
},

切换路由后,新页面要滚动到顶部或保持原先的滚动位置怎么做呢

const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes,
    scrollBehavior(to, from, savedPosition) {
        if (savedPosition) {
            return savedPosition;
        } else {
            return { x: 0, y: 0 };
        }
    }
});

Vue路由怎么跳转打开新窗口

const obj = {
    path: xxx,//路由地址
    query: {
       mid: data.id//可以带参数
    }
};
const {href} = this.$router.resolve(obj);
window.open(href, '_blank');