目 录CONTENT

文章目录

开发之JS|通过原生来实现一个简单的拦截器功能

Dioxide-CN
2022-01-31 / 0 评论 / 2 点赞 / 27 阅读 / 3,429 字
温馨提示:
本文最后更新于 2022-04-20,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

除夕快乐!最近一直在开发Springboot都忘记照顾博客了,正好把最近研究的拦截器拿出来卖弄一下~

什么是拦截器?

通俗点讲,就是在某一组条件条件未达到的情况下,禁止访问某一组页面;咱们举个栗子,我有一个页面,其路径为 dioxide-cn.ink/view/demo.html ,我只希望给我点过赞的读者能访问,那么没有点赞的读者就访问不了,这样我们就吧没有点赞的读者拦截在了页面外面;

我们在小学二年级的时候就已经学过了 Springboot 的拦截器 和 Vue 的页面路由,我们顺着前人的智慧现在我们来通过原生 js 来实现一个拦截器的功能,并且让他看起来更容易配置和理解一些。为了提高学习的主动性,示例代码中使用一个了 “ 函数的链式调用 ” 、“ 类与对象的开发 ” 和 “ ajax在类方法中的同步调用 ”,可能不太适合刚入门 js 的读者~

思路与构造:

在上文中,我们提到了这样一段话 “ 在某一组条件条件未达到的情况下,禁止访问某一组页面 ” 从这句话中,我们可以直接剖析出对象的属性 —— 这个对象需要 “ 一组条件 ” “ 被拦截后重新定向到的页面 ” 和 “ 一组被拦截的目标页面 ” 那么我们先把这个对象实现出来:

group1: {
    desc: '需要token才能访问',
    redirect: '404',
    pages: [
        '/view/demo.html'
    ]
}

为了方便阅读我们添加了一个 desc 属性来注释该组是需要什么条件才能访问 pages 中的页面。这样,我们就得到了一组需求,但是我们似乎要配置很多组不同的 加权配置,那么我们可以在外部再构造一个对象或一个对象数组来存放这些配置对象。为了方便叙述,这里我们将封装在 pages 对象中作为嵌套对象;

很明显,想要实现group1的拦截方法,我们需要从定义好的配置中我们能分析出我们需要的如下几个方法:

  1. 检测当前访问的页面是在 pages 数组中;
  2. 如果满足那么我们就需要判断 group1 是否满足我们所需要的权限;
  3. 如果权限也满足那么我们就允许访问者留在页面内,否则将被重定向至 404.html 页面;

理论存在,实践开始。为了提高阅读性和理解我们定义两个类(Util 工具类 和 Condition 条件类),其中 条件类 我们用来定义一些条件判断方法,他们的返回值均为布尔类型;而 工具类 我们用来存放一些数据处理和条件组的综合判断(如:重定向页面、拦截器封装等);

既然 工具类 需要调用 条件类 的方法,那么我们就需要让 Util 继承 Condition 的方法,现在我们来构造出这两个类:

class Condition {}
class Util extends Condition {}

我们类方法已经构思好了,现在我们用 token 来举例子(后端我已经用 springboot 写好了 token 的验证接口,前端 token 被存储在了 cookie 中)这样我们的条件就是拦截所有没有 token 或 伪造token 的用户。这里我们使用链式函数首先对有无 token 进行判断,再执行 token 是否有效的判断;考虑到条件可能不止存在1个,我们需要定义一个条件组判断器,用来判断所有传入的条件的返回结果,即:一否全否,全真则真,现在我们来实现这些代码:

/**
 * condition 条件库
 * @author Dioxide.CN 2022/1/31
 */
class Condition {

    /**
     * 检验token是否有效
     * @return {Boolean} true: 有效; false: 不存在或无效;
     */
    trueToken() {
        if(this.tokenStatue){
            var    ret = true
            $.ajax({
                async: false, //同步执行
                url: 'http://localhost/verifyToken',
                type: 'post',
                data: {
                    'token': $.cookie('token')
                },
                success: function(res) {
                    ret = res
                }
            })
            return ret
        } else {
            return false
        }
    }

    /**
     * @java public boolean ifToken(){}
     * @retun {Boolean} true: 在页面内; false: 不在页面内;
     */
    ifPage(pages) {
        var curr = window.location.pathname
        for(var key in pages) {
            if(curr.indexOf(pages[key])==0) {
                return true
            }
        }
        return false
    }

}

/**
 * util 工具库
 * @author Dioxide.CN 2022/1/31
 */
class Util extends Condition {

    /**
     * 是否存在token
     * @return {Boolean} true: 存在; false: 不存在;
     */
    ifToken() {
        if($.cookie('token') == undefined) {
            this.tokenStatue = false
        } else {
            this.tokenStatue = true
        }
        return this
    }

    /**
     * 重定向方法
     * @param {String} page 目标页面名
     */
    redirectTo(page) {
        window.open('/' + page + '.html','_self');
    }

    /**
     * 条件集
     * @param {Array} 条件返回组; 布尔二维数组
     * @return {Boolean} true: 条件集为真; false: 条件集为假;
     */
    getBoolean(...bool) {
        var last = true
        for(var key of bool[0]) {
            last = last && key
        }
        return last
    }

    /**
     * 在页面内且条件集为真时才能访问
     * @java public void intercept(){}
     * @param {Object} target 配置组
     * @param {Array} condition 条件集
     */
    intercept(target, ...condition) {
        if(this.ifPage(target.pages)) {
            if(!this.getBoolean(condition)) {
                this.redirectTo(target.redirect)
            }
        }
    }}
}

这里的 Util.intercept() 就是我们所需要的拦截器驱动了,有了这些判断我们可以很容易的实现我们想要的各种拦截器功能:

const util = new Util() //实例化util

/**
 * 拦截区
 * @example util.intercept(配置组, 条件集)
 * @example util.intercept(pages.group1,util.ifToken().trueToken())
*/
util.intercept(pages.group1,util.ifToken().trueToken())

这样我们就完成了原生 js 实现拦截器的功能~

附加链接:

Giteehttps://gitee.com/dioxide-cn/js-component-library

2

评论区