vue-router

本文详细介绍了Vue.js中的路由创建,包括引入和安装Vue Router、定义路由、创建路由实例以及路由出口的设置。接着讲解了路由跳转的声明式和编程式方法,以及如何传递参数。动态路由和路由参数的使用也被提及,特别是params和query的区别。最后,文章阐述了路由导航守卫的概念,包括全局、路由独享和组件内的导航守卫,用于控制路由跳转时的权限和行为。

一、创建路由

路由router/index.js

// 1 引入vue和vue-router
import Vue from 'vue';
import VueRouter from 'vue-router';

// 2 通过 Vue.use() 明确地安装路由功能
Vue.use(VueRouter);

/*
 *  3 定义一些路由(即一个对象代表一个路由,都存放在数组routes中,也可以由外部导入)
 *  每个路由都需要映射一个组件(即一个path对应一个component)
 *  其他配置项包括name redirect meta等等
*/
const routes = [
  {
    // 会拼接到地址栏, 名字是自定义的('/'代表页面默认打开时的路由)
    path: '/',
    // 路由重定向(即只要到该路由就会被重定向到某路由,此处为'/home',所以此处无需映射组件)
    redirect: '/home'
  },
  {
    // 路由路径(当地址栏显示/home时,app.vue中的router-view便显示Home.vue的内容)
    path: '/home',
    // 路由名称(路由跳转时可以通过path,也可以通过name)
    name: 'home',
    // 组件懒加载(即处于此路由时才会导入该组件,而不是一开始就导入组件,利于性能优化)
    // 也可以由其他文件直接导入
    component: () => import('../views/Home.vue'),
    // 默认显示子路由one
    redirect: '/home/one',
    // 路由的子路由(子路由的出口即router-view是需要写在其父级路由中的)
    children:[
         // 写法1,不加'/', 即代表'/home/list'
        {path: 'one', component: () => import('../views/One.vue')},
         // 写法2,加'/', 就需要写完整路由,也代表'/home/list'
        {path: '/home/two', component: () => import('../views/Two.vue')}
    ],
    // 路由源信息(按需使用)
    meta: {
        title: '主页',// 标题
        icon: 'el-icon-s-home',// 图标
        roles: ['admin', 'editor'],// 路由权限时使用
        keepAlive: true,// 组件缓存时使用
    } 
  }
];

// 4 创建路由实例
const router = new VueRouter({
  // history模式地址栏不会显示#号,hash模式会显示#号,默认值是hash
  mode: 'history',
  routes
});

// 解决重复点击同一个路由时,控制台出现报错问题
// 报错内容:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation
const VueRouterPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (to) {
  return VueRouterPush.call(this, to).catch(err => err)
}
VueRouter.prototype.replace = function replace (to) {
  return VueRouterPush.call(this, to).catch(err => err)
}

// 5 导出路由实例
export default router

二、路由出口

一级路由的出口一般在app.vue中

<template>
  <div id="app">
    <router-view />
  </div>
</template>

二级及以上路由的出口,一般是在其父级路由相对应的组件内部

<!-- 如一级路由home的子路由出口是在Home.vue的内部 --> 
<template>
    <div>
        我是home页面
        <main>
            <!-- home子路由的出口 --> 
            <router-view />
        </main>
    </div>
</template>
<script>
export default {
    name: 'Home',
};
</script>

三、路由跳转

路由的跳转方式有两种,一种是声明式,一种是编程式(常用)

1、声明式路由(通过html标签跳转)

必传参数

        <!-- 
            to 必传参数,表示指定跳转的路径:
            1、字符串形式,如'/home/one'命名的路由(必须在router/index.js中有);
            2、对象形式,如{ path: '/home/one', query: { id: 1 } }(query是可传递的参数)

            注:路径必须是完整路径,否则如果写成'home/one'的类型,会直接拼接在当前路径的后面
         -->
        <router-link to="/home/one">one</router-link>
        <router-link to="/home/two">two</router-link>

其他参数

        <!-- 
            1、tag 可选参数
                表示使用什么标签来渲染
                默认值是a,也可以是div、button等
            2、replace 可选参数
                表示是否使用replace方法来跳转
                默认是false,表示使用push方法来跳转
            3、append 可选参数(不推荐使用)
                表示是否将to的值追加到当前的路径后面
                默认是false
            4、active-class 可选参数
                表示当前路由匹配时的class
                默认是router-link-active
            5、exact-active-class 可选参数
                表示当前路由完全匹配时的class
                默认是router-link-exact-active
            6、event 可选参数
                表示触发跳转的事件
                默认是click
         -->
        <router-link 
            to="/home/one"
            tag="button"
            replace="true"
            append="false"
            active-class="active"
            exact-active-class="exact-active"
            event="click"
            >one</router-link>

2、编程式路由(通过js跳转)

常用的跳转方式

// 封装一个函数,通过事件调用即可
methods: {
  goOne() {
    // 1、push (跳转到指定的url,在history中添加记录)
    // this.$router.push('/home/one')
    // this.$router.push({ path: '/home/one' })
    // this.$router.push({ path: '/home/one', query: { a: 1 } })
    // this.$router.push({ name: 'HomeOne' })
    // this.$router.push({ name: 'HomeOne', params: { a: 1 } })

    // 2、replace重定向(跳转到指定的url,不在history中添加记录)
       this.$router.replace('/home/one');// 推荐写法
    // this.$router.replace({ path: '/home/one' })
    // this.$router.replace({ path: '/home/one', query: { a: 1 } })
    // this.$router.replace({ name: 'HomeOne' })
    // this.$router.replace({ name: 'HomeOne', params: { a: 1 } })
  }
}

其他跳转方式

this.$router.forward();    // 前进
this.$router.back();       // 后退
this.$router.go();         // 向前或向后跳转n个页面(n/-n)

四、路由传参

具体的写法在上面路由跳转时已说明,此处主要说明params和query的区别以及如果接收参数

1、参数接收

this.$route.params.id
this.$route.query.id

2、query和params的区别

1、搭配方式不同:query通常搭配path使用、params通常搭配name使用;

2、地址栏是否显示:query地址栏显示参数,params,地址栏不显示参数;

3、刷新是否造成数据丢失:query传值页面刷新也存在,params一刷新就没了(解决方案:在配置路由时加入占位符)

五、动态路由 

在path配置一个字段“:name”,它表示此字段是动态的。此时不管是路径'/home/two/Tom',还是'/home/two/John’,或者是其他的,都会跳转到此路由。

router/index.js

{
    path: '/home/two/:name', 
    component: () => import('../views/Two.vue')
},

跳转

const name = 'xxx'; // name是动态变化的
this.$router.replace('/home/one/'+name);

六、路由导航守卫

1、全局导航守卫

router/index.js

// 全局导航守卫(即在路由跳转前后做一些事情)
// 1.全局前置守卫
router.beforeEach((to, from, next) => {
    // 1.1 判断是否需要登录
    if (to.meta.requireAuth) {
        // 1.1.1 判断是否登录
        if (store.state.token) {
            next();
        } else {
            // 1.1.2 未登录则跳转到登录页面
            next({
                path: '/login',
                // 1.1.3 将跳转的路由path作为参数,登录成功后跳转到该路由
                query: {redirect: to.fullPath}
            })
        }
    } else {
        next();
    }
    // 1.2 判断是否需要权限
    if (to.meta.roles) {
        // 1.2.1 判断是否有权限
        if (store.state.roles.some(role => to.meta.roles.includes(role))) {
            next();
        } else {
            // 1.2.2 无权限则跳转到401页面
            next({
                path: '/401',
                // 1.2.3 将跳转的路由path作为参数,登录成功后跳转到该路由
                query: {redirect: to.fullPath}
            })
        }
    } else {
        next();
    }
});
// 2.全局后置守卫(后置守卫没有next参数)
router.afterEach((to, from) => {
    // 2.1 设置标题
    document.title = to.meta.title;
    // 2.2 设置面包屑
    store.commit('setBreadcrumb', to);
});

2、路由独享守卫

路由独享守卫,在进入该路由前执行的函数,可以用来判断是否有权限进入该路由,如果没有权限则跳转到其他路由。

{
    path: '/home',
    component: () => import('../views/Home.vue'),
    beforeEnter: (to, from, next) => {
      next();
    }
  },

3、组件内导航守卫

组件内导航守卫,只在当前组件生效,父子组件互不影响

export default {
    name: 'Home',
    // 导航守卫
    beforeRouteEnter(to, from, next) {
        console.log('beforeRouteEnter')
        next()
    },
    beforeRouteUpdate(to, from, next) {
        console.log('beforeRouteUpdate')
        next()
    },
    beforeRouteLeave(to, from, next) {
        console.log('beforeRouteLeave')
        next()
    },
    methods: {
        
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

[chao]

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值