如何使用JavaScript构建模态框插件

特别声明:为感谢社区广大朋友对小站的支持,自2019年10月1日至2019年11月11日开通年费VIP通道,年费价格为 ¥299.00元。如果您喜欢小站的内容,可以点击开通会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!(^_^)

作为一位Web开发人员而言,模态框(Modal)并不会陌生。就我个人而言,我更为熟悉的是怎么通过CSS来编写一个模态框以及怎么通过CSS给模态框添加一些动效。正好最近工作中也和Modal框杠上了。另外想更好的设计一个模态框用来满足业务需求的普遍性和实用性,甚至是达到可配置性。所以一直在探究模态框相关的知识,同时正好看到了@Ken Wheeler的教程,对于我这样的菜鸟,能很好的了角如何使用原生的JavaScript来构建一个可用的模态框插件,另外为以后如何使用Vue构建更为灵活的模态框组件打下坚实的基础。如果你对该文章感兴趣,或者你也正在加强JavaScript的学习和实战,欢迎继续往下阅读,或许对你有所帮助。

模态框是什么

模态框在前端组件中是一个非常常见的组件。其位于Web应用程序主窗口之上的一个元素。他创建了一个新的模式,该模式禁止用户操作应用程序的主窗口,但它以弹窗的模式在应用程序主窗口之上显示。用户可以在返回应用程序主窗口之前与弹框进行交互操作。

模态框的设计,如果设计或执行不好将会影响主链路的操作,防碍任务的完成。为了确保不影响主链路的操作,一个模态框至少应该包括下面内容:

一个优秀的Modal框主要包含的部分有:

  • 模态框的蒙层:modal-overlay
  • 模态框头部:modal-header
  • 模态框主体:modal-body
  • 模态框脚部:modal-footer
  • 关闭按钮:modal-close

刚才也提到过,模态框毕竟是在应用程序主窗口上显示,所以需要给用户提供关闭模态框的途径。常见的方式有:

  • 取消按钮
  • 关闭按钮
  • ECS
  • 点击模态框窗体外的区域关闭模态框

因此,我们要设计一个模态框,也需要考虑这些因素。

构建模态框插件

接下来,我们来看看怎么使用原生的JavaScript来构建一个模态框插件。通过这个学习你将掌握或需要掌握以下几个知识点:

  • CSS的transitionanimation相关知识点
  • JavaScript DOM操作相关知识点
  • JavaScript 构造器和构造函数
  • JavaScript 事件监听
  • JavaScript 函数

如果你是一个初学者,还是值得花一点时间阅读该文,如果你是位JS大神,欢迎您拍正文章中的不足。

选择设计模式

首先要确定设计模态弹出框的结构并选择一个设计模式。我们的目的是要创建一个模态弹出框,并且可以真正的运用于我们的项目中。这里将会用到闭包相关的知识,因为闭包可以用来创建一个私有域,可以在其中控制提供哪些数据:

// 创建一个立即调用的函数表达式来包装我们的代码
(function() {
    var privateVar = "在控制台中console.log找不到我"
}());

我们想为插件添加一个构造函数方法,并将其公开。IIFE 是全局的,因此this的关键词指向的是window。让我们使用this将构造函数附加到全局作用域:

// 创建一个立即调用的函数表达式来包装我们的代码
(function(){
    // 定义构造器
    this.Modal = function () {

    }
}())

我们将Modal变量指向一个函数,从而创建一个函数对象,现在我们可以用new关键词实例化它,如下所示:

var myModal = new Modal()

console.log(myModal) // => Object {}

上面的代码创建了一个对象的新实例。不幸的是,我们的对象在这一点上并没有做什么,所以接下来给这个对象加点其他的东西。

有关于闭包更多的知识点可以阅读下面相关文章:

选项(Options)

回顾一下我们的需求,我们首要的任务是允许用户自定义选项(options)。实现这一点的方法就是创建一组默认的选项,然后将其与用户提供的对象合并。

(function(){
    // 定义构造函数
    this.Modal = function () {
        // 创建引用的全局元素
        this.closeButton = null; // 关闭按钮
        this.modal = null; // 模态弹出框
        this.overlay = null; //模态弹出框蒙层

        // 自定义默认选项
        var defaults = {
            className: 'fade-and-drop',
            closeButton: true,
            content: '',
            maxWidth: 600,
            minWidth: 280,
            overlay: true
        }

        // 通过扩展arguments中传递的缺省值来创建选项
        if (arguments[0] && typeof arguments[0] === 'object') {
            this.options = extendDefaults(defaults, arguments[0])
        }
    }

    // 使用用户选扩展默认值的方法
    function extendDefaults(source, properties) {
        var property;
        for (property in properties) {
            if (properties.hasOwnProperty(property)) {
                source[property] = properties[property]
            }
        }
        return source
    }
}())

首先,创建了被引用的全局元素。这些都很重要,这样一来就可以在插件的任何地方引用Modal。接下来,我们添加了一个默认(defaults)选项对象。如果用户不提供选项(options),就会使用默认选项;如果用户提供了就会覆盖默认选项。那么我们怎么知道用户有没有提供选项呢?这里的关键是arguments对象。这是每个函数内部的一个神奇对象,它包含通过参数传递给它的所有东西的数组。因为我们只期望一个参数,一个包含插件设置的对象,所以我们检查以确保arguments[0],并且它确实是一个对象。

如果条件达得到,就会使用extendDefaults私有域的方法合并这两个对象。extendDefaults接受一个对象,将会遍历它的属性(properties),如果不是其内部属性(hasOwnProperty),就将它分配给源对象(source)。我们现在可以配置我们插件和选项对象。

var myModal = new Modal({
    content: 'Howdy',
    maxWidth: 600
})

这个时候在控制台中打印出myModal,其结果如下图所示:

为了提供一个公共主法,可以将它附加到Modal对象的原型上(prototype)。当你向对象的原型中添加方法时,每个新实例共享相同的方法,而不是为每个实例创建新方法。这在性能上也具有较大的优势,除非有多级子类化,不然在这种子类化中,遍历原型链会抵消性能提升。我们还添加了注释,并对组件进行了结构化。这样我们就有三个部分

剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/javacript/building-your-own-javascript-modal-plugin.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部