vue-路由

  • 背景:vue中如果想从一个页面到达另一个页面,可以使用路由来实现。
    官方文档-vue-router
    以下都是个人看文档和结合实际开发时用到的理解:
    路由主要为我们实现以下功能:
  • 嵌套的路由/视图表:
    如:
    app.vue
    <div id="app">
        <router-view />
    </div>

router/index.js

import Vue from 'vue';
import Home from '../views/Home.vue';
import About from '../views/About.vue';

const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home,
        children: [{path: 'about', component: About}]
    },
    {
        path: '/home',
        name: 'Home',
        component: Home,
        children: [{path: 'about', component: About}]
    }
];

const router = new VueRouter({
    mode: 'history',
    routes
});

export default router;


home.vue

    <div class="home">
    home
        <router-view></router-view>
    </div>

其中router-view是最顶层的出口(也就是最开始渲染的那一层),渲染最高级路由匹配到的组件,如app.vue中,在路由中设定了默认就是渲染了home.vue。同样地,一个被渲染组件同样可以包含自己的嵌套router-view, 也就是home.vue页面中也可以渲染自己的子路由,使用children属性来进行设置,其中嵌套了一个路由路径叫做about,渲染的组件为about.vue。

访问顶层出口(它的渲染组件为home.vue):
在这里插入图片描述
访问嵌套在home.vue中的路由:
在这里插入图片描述
有什么用?可以用来做点击选项卡切换不同的内容:

home.vue

<template>
    <div class="home">
        home
        <router-link to="/home/login">登录</router-link>
        <router-link to="/home/register">注册</router-link>
        <router-view></router-view>
    </div>
</template>

router/index.js:

import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
import About from '../views/About.vue';
import Login from '../views/login.vue';
import Register from '../views/register.vue';
Vue.use(VueRouter);
const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home,
        children: [
            {path: 'about', component: About},
            {path: 'login', component: Login},
            {path: 'register', component: Register}
        ]
    },
    {
        path: '/home',
        name: 'Home',
        component: Home,
        children: [
            {path: 'about', component: About},
            {path: 'login', component: Login},
            {path: 'register', component: Register}
        ]
    }
];

const router = new VueRouter({
    mode: 'history',
    routes
});

export default router;

如下图:
在这里插入图片描述
在这里插入图片描述

  • 路由参数、查询、通配符: 平时我们会在url跳转(通常会使用Window Location进行跳转),跳转的时候自己拼接参数带过去,到达目标url又从链接上取(封装方法进行获取)下来,。而vue路由解放了我们双手——router的实例方法已经帮助我们封装好了这些方法。我们可以直接使用:
跳转链接,常用的有两种方式:

this.$router.push: 这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。类似location.href(path)

        handleClick() {
            this.$router.push('/userinfo');
            console.log(window.history);
        }

跳转的时候会有记录(没跳转之前我浏览器中一共有13条历史记录):
在这里插入图片描述
this.$router.replace: 它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录,类似于location.replace(path)

        handleClick() {
            this.$router.replace('/userinfo');
            console.log(window.history);
        }

跳转之后没有记录,浏览器不能回退到前一个页面(没跳转之前我浏览器中一共有13条历史记录):
在这里插入图片描述
添加参数:两种跳转方式添加参数方式类似
1.命名的路由:也就是参数通过vue的router实例去传递,参数不会在链接上显示出来。如果我们传递的数据太大了,直接拼接在url上,链接请求的过程就是get请求,参数是有内存限制的,数据太大的时候,可能会导致路由瘫痪。这时候可以通过命名的路由来实现。

        handleClick() {
            this.$router.push({name: 'userinfo', params: {userId: '123'}});
            console.log(this.$router);
        }

在这里插入图片描述
获取(在userinfo.vue中):

        console.log(this.$route.params.userId);

如下图:
在这里插入图片描述
2.带查询参数:也就是我们发送的参数,都会在url上显示出来,这时候就是比较小的数据,相当于get请求

        handleClick() {
            this.$router.push({path: 'userinfo', query: {userId: '123'}});
            console.log(this.$router);
        }

获取(在userinfo.vue中):

        console.log(this.$route.query.userId);

如下图:
在这里插入图片描述
注意: 两者除了在表现形式不一致外,还有一个区别:
在使用 命名的路由 传递参数,跳转过去后刷新页面,params会丢失,而query不会。这时候我们也可以通过缓存的方式进行存储解决这个问题。

扩展问题:如果我们传递的参数数据太庞大,超过了query允许的范围,又不想用缓存来处理params刷新丢失的问题,那么如何解决?个人建议:庞大的数据需要不同页面传递,,或许是后端接口设计得不合理,可以考虑协商调整接口,使用查询参数传递关键信息过来,然后在目标页面进行接口请求。

前端的工作,不仅仅是为了把数据展示上去就好,如果接口设计得不合理,会导致本来简单的事情在前端页面处理起来很繁杂,在开发过程中,如果项目业务逻辑复杂,拆分组件的时候,会根据前端的知识进行组件化拆分,建议也要结合接口进行验证拆分得是否合理(bug也会降低很多),不然就会更复杂化流程。

  • 基于 Vue.js 过渡系统的视图过渡效果:vue提供了 以下标签,可以用来进行过度:
        <router-link to="/home/login">登录</router-link>
        <router-link to="/home/register">注册</router-link>
        <div @click="handleClick">
            个人中心
        </div>
        <transition name="fade" mode="out-in">
            <router-view></router-view>
        </transition>
.fade-enter-active,
.fade-leave-active {
    transition: opacity 0.3s ease;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
    opacity: 0;
}

写css的类名也是有规则的,官方文档给出这样的解释:
在这里插入图片描述
在这里插入图片描述
其中v就是我们定义的属性name的属性值

过渡模式:由于transition 的的默认行为 - 进入和离开同时发生, 同时生效的进入和离开的过渡不能满足所有要求,也就是过渡起来很不自然,所以 Vue 提供了过渡模式
in-out:新元素先进行过渡,完成之后当前元素过渡离开。

out-in:当前元素先进行过渡,完成之后新元素过渡进入。

上面的代码,当我们点击登录或者注册的时候,路由切换会时内容更换相对平缓,有一个无到有的动画效果。

也可以看看 官方transitions

上面的动画样式是自己定义的,也可以结合第三方动画库Animate.css来实现。

  • 细粒度的导航控制
    全局守卫:有前置和后置守卫,可以理解为监督路由变更的哨兵:
    beforeEach: 前置守卫, 进入路由之前,使用场景:如果一个页面需要登录才能进去,我们可以在此进行拦截,当前用户没有登录,就拦截转到登录页面。
    to: 目标路由
    from: 要离开的路由
    next: 进行管道中的下一个钩子,使用了全局守卫,一定要确保这个也执行了, 否则会中断跳转。
const router = new VueRouter({
    mode: 'history',
    routes:[]
});
router.beforeEach((to, from, next) => {
    console.log(to, from);
    next();
});

如从 到达 home到userinfo
在这里插入图片描述
router.afterEach: 全局后置守卫,到达目标路由后

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

上述两个守卫是全局的,对所有的路由都生效,同样我们可以设置单个路由独享的守卫,路由独享守卫,只有这一个:

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

有了全局守卫和路由独享守卫外,还有组件内的守卫

<template>
    <div class="home">
        home
        <router-link to="/home/login">登录</router-link>
        <router-link to="/home/register" exact>注册</router-link>
        <div @click="handleClick">
            个人中心
        </div>
        <transition name="fade" mode="out-in">
            <router-view></router-view>
        </transition>
    </div>
</template>

<script>
export default {
    name: 'Home',
    data() {
        return {
            msg: 'hello'
        };
    },
    components: {
    },
    // 路由进入前
    beforeRouteEnter(to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
        // console.log(this.msg); //=>TypeError
        console.log('beforeRouteEnter');
        next();
    },
    // 路由更新前
    beforeRouteUpdate(to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
        this.msg = 'world';
        console.log('beforeRouteUpdate:', this.msg);
        next();
    },
    beforeRouteLeave(to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
        console.log(to, from, 'beforeRouteLeave:', this.msg); //=>hello
        next();
    },
    methods: {
        handleClick() {
        }
    }
};
</script>

如下图:

初次进入当前路由(调用beforeRouteEnter):
在这里插入图片描述
路由更新:这里指的是子路由改变(beforeRouteUpdate):
在这里插入图片描述
离开当前路由:

在这里插入图片描述
跳转到userinfo路由(调用了beforeRouteLeave):
在这里插入图片描述
官方给的导航解析流程:
在这里插入图片描述
理解:
1.假设/home是从/other这个路由过来的,当在浏览器中打开的时候,就会触发导航(1),/other这个组件会失活,它会调用组件守卫beforeRouteLeave(2),接着调用全局守卫beforeEach(3),进到/home前会先调用独享路由beforeEnter(5),有异步路由也调用(6),当home.vue组件被激活 时候调用 组件守卫beforeRouteEnter(7)、(8),接着导航被确认跳来了/home(9),再调用全局守卫afterEach,接着就触发DOM更新(11),然后触发next(12)
2. 如果从/home跳去它的嵌套子路由/home/login,就会重用home.vue,才会调用组件守卫beforeRouteUpdate(4)

如下图,初次进入home会触发以下守卫:
在这里插入图片描述
点击登录,会重用home,组件守卫只会调用一个beforeRouteUpdate,全局守卫都会调用了:
在这里插入图片描述
点击去到个人中心:会调用所有的全局守卫,home组件的beforeRouteLeave,以及userinfo组件的beforeRouteEnter
在这里插入图片描述

  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级:vue-router默认的模式为hash模式,它一共有两种模式:
    1.hash
    2.history
    设置方式:在创建路由实例的时候:

    
    const router = new VueRouter({
        mode: 'history', //默认值为hash
        routes:[]
    });
    

区别:
两者最明显的区别就在于表现形式上:
hash会有#:
在这里插入图片描述
history没有#:
在这里插入图片描述
区别二:
hash模式:如果输入的路由不存在,页面同样也会自动跳到首页。

history模式:如果输入的路由,不存在,页面就会404,这时候前端可以进行设置通用路由覆盖所有:

const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})

这样,找不到对应路由的配置的时候,就都会进入这个页面,就不会404了,当然也可以让后端进行配置这些。

下面的这三个先不写了,可以去官网看

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值