资讯专栏INFORMATION COLUMN

vue router实现拦截和类似github的页面加载

daryl / 1946人阅读

摘要:最近想写个简单来练习下全家桶,其中特别想实现类似的页面加载行为。翻了下,提供导航钩子给开发者实现导航拦截但实验后发现,当钩子执行的时候的状态已经改变而且难以实现进度条。

0x00

最近想写个简单blog来练习下vue全家桶,其中特别想实现类似github的页面加载行为。

0x01

翻了下api,vue-router提供导航钩子给开发者实现导航拦截

router.beforeEach((to, from, next) => {  })

但实验后发现,当钩子执行的时候url/hash的状态已经改变而且难以实现进度条。

0x02

翻查源代码后发现更改url主要是在history实例中进行,其中history暴露一个listen的方法来监听路由的改变从而更新vue的root元素的路由值。

    history.listen(route => {
      this.app._route = route
    })

在这里只要延迟_route的赋值就能延迟UI和url的更新,甚至能替换路由

0x03

最终代码,这里没有用作进度条,配合store可以实现类似github的进度条指示器,以及超时处理

// 定义一个正在加载的Route的访问器
Object.defineProperty(Vue.prototype, "$routePending", {
    get () {
        return this.$root._routePending;
    }
});
//hook vm创建
Vue.mixin({
    /**
     * hook route updated
     */
    beforeCreate () {
        if (this.$options.router) {
            //定义一个响应式属性
            Vue.util.defineReactive(this, "_routePending", null);
            //延迟赋值并做预加载
            this._router.history.listen(route => {
                this._routePending = route;
                Promise.resolve()
                    .then(() => {
                        //过滤非执行中的route
                        if (route != this._routePending) {
                            return;
                        }
                        if (route.matched) { //路由有匹配的组件
                            let reduce = route.matched.reduce((list, item) => {
                                Object.keys(item.components).forEach(k => {
                                    let component = item.components[k];
                                    if (component.preFetch) {
                                        list.push(component.preFetch); //所有组件的preFetch入列
                                    }
                                });
                                return list;
                            }, []);
                            if (reduce.length > 0) {
                                return Promise.all(reduce.map(fn => fn(route)));
                            }
                            return route;
                        }
                    })
                    .then(() => {
                        //过滤非执行中的route
                        if (route != this._routePending) {
                            return;
                        }
                        //
                        this._route = route;
                        this._routePending = null;
                    })
                    .catch(e => {
                        console.warn(e);
                        this._router.replace("/500");
                    });
            });
        }
    }
});

已知问题:

原来的导航钩子可能出现问题

PS:文中很可能出现错误,这里给出一个思路

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81635.html

相关文章

  • 前端路由原理解析实现

    摘要:如何实现前端路由要实现前端路由,需要解决两个核心如何改变却不引起页面刷新如何检测变化了下面分别使用和两种实现方式回答上面的两个核心问题。 原文链接:github.com/whinc/blog/… 在单页应用如此流行的今天,曾经令人惊叹的前端路由已经成为各大框架的基础标配,每个框架都提供了强大的路由功能,导致路由实现变的复杂。想要搞懂路由内部实现还是有些困难的,但是如果只想了解路由实现基本...

    lavor 评论0 收藏0
  • 浅谈使用 Vue 构建前端 10w+ 代码量页面应用开发底层

    摘要:其实就是我们开始挂载上去的我们在这里出去,我们就可以在回调里面只处理我们的业务逻辑,而其他如断网超时服务器出错等均通过拦截器进行统一处理。 showImg(https://segmentfault.com/img/remote/1460000015472616?w=845&h=622); 开始之前 随着业务的不断累积,目前我们 ToC 端主要项目,除去 node_modules, bu...

    rickchen 评论0 收藏0
  • 浅谈使用 Vue 构建前端 10w+ 代码量页面应用开发底层

    摘要:其实就是我们开始挂载上去的我们在这里出去,我们就可以在回调里面只处理我们的业务逻辑,而其他如断网超时服务器出错等均通过拦截器进行统一处理。 showImg(https://segmentfault.com/img/remote/1460000015472616?w=845&h=622); 开始之前 随着业务的不断累积,目前我们 ToC 端主要项目,除去 node_modules, bu...

    Backache 评论0 收藏0
  • 记一次vue仿网易云音乐页面应用

    摘要:说明一直想做一个基于的项目但是因为项目往往要涉及到后端的知识不会后端真的苦所以就没有一直真正的动手去做一个项目。直到发现上有网易云音乐的才开始动手去做。仅仅完成了首页登入,歌单,歌曲列表页。 说明 一直想做一个基于VUE的项目,但是因为项目往往要涉及到后端的知识(不会后端真的苦),所以就没有一直真正的动手去做一个项目。直到发现GitHub上有网易云音乐的api NeteaseCloud...

    hqman 评论0 收藏0
  • vue开发项目完全指南

    摘要:有两种方法,一种是在开发环境中设置通过的,另一种是在服务器上修改的配置设置。这样我们以后使用访问接口就可以不加了,打包后访问也不用手动去除统一管理在项目开发过程中,会涉及到很多接口的处理,当项目足够大时,就需要统一管理接口。 这篇文章总结了vue项目的所遇到的问题,包括跨域、用户认证、接口统一管理、路由配置、兼容性处理,性能优化等内容。 项目github地址 : 前端 https:...

    leoperfect 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<