最近使用require尝试开发了一个弹窗组件,所以把一些组件化的思想和过程记录下来。

使用的库

  • jQuery
  • require
  • jQueryUI

实现的功能

  • 三种流行的弹窗
  • 带有宽高位置设置
  • 可以设置按钮的内容以及显示内容
  • 可以设置是否模态
  • 可以添加额外的皮肤
  • 拥有自定义的事件机制 一个click事件触发多个自定义事件

Markdown

基本思想

这个来源于网上的材料,我照着自己实现了一下,来记录一下我觉得的重点,最关键的是一种组件化的思想,也就是组件和组件之间的依赖关系。require是个非常棒的东西。 定义一个组件,然后把这个组件暴露出去 并在main里进行调用。另外一点组件最好是由一个抽象类统一进行管理,让抽象类调用一些抽象的方法,然后让具体的类进行一个实现。

调用和实现

调用方式

$('.confirm').click(function () {
        new w.window().confirm({
            title:"系统消息",
            content:"您确定要删除这个文件吗",
            confirmBtn:"是",
            cancelBtn:"否",
            dragHanle:".wiw_header",
            hasMask:true,
            maskFlash:true,
        }).on("confirm",function () {
            alert("sure");
        }).on("cancel",function () {
            alert("cancel");
        })
    })

以上是一个调用实例,首先添加事件然后传参进行new,其中参数用了json进行传输,我认为在不跨前后端的情况下不是很需要传入字符串形式的json,对象形式的json可以和方便的传送回调函数

因为实现了三种弹窗,所以支持alert和promot 传进去的参数类型也有所不同 在window构造函数中会设置一些默认的值,没有传参也已正常的运行

整体框架

Wiw.prototype = $.extend({},new widget.widget(),{...自定义的方法}

首先利用对象的合并,让原型对象变成一个抽象类与自定义方法的合体。

confirm:function (cfg) {
        $.extend(true,this.config,cfg,{winType:"confirm"});
        this.render();
        return this;
    }

这里是实际调用的中心, 首先会进行一个深层次的对象合并 接着执行render()方法

这个方法来源于抽象类,他扮演调用中心的角色,而具体的实现则由window来实现

render:function (container) {
        this.renderUI(); //建造盒子和内容
        this.handlers = {}; //初始化自定义事件容器
        this.bindUI(); //绑定事件
        this.syncUI(); //设置样式
        $(container || document.body).append(this.boundingBox); //所有完成 添加到文档
    },

所有的弹窗都被拆分成了这么几个抽象步骤,在这些方法中进行一个具体实现,可以很好的提高代码可读性。

而摧毁盒子也是如此的结构

destory:function () {
        this.destructor();
        this.boundingBox.off();
        this.boundingBox.remove();
    }

所有的方法都是公用的 比如alert 和 confirm 调用的都是同样的方法 ,但区分在于在自身的config属性中添加winType 通过对于自身类型的识别,我们可以做到不同的措施。

自定义事件的实现

on:function (type,handler) {
        if(typeof this.handlers[type] == "undefined"){
            console.log(type);
            this.handlers[type] = [];
        }//如果在字典中响应类型没有事件存储 就创建一个数组以便村粗

        this.handlers[type].push(handler);
        return this;
    },
    fire:function (type,data) {
        //检测相应类型数组是否存在 存在则全部吐出来执行
        //如果传进来了输入就放入参数之中调用
        if(this.handlers[type] instanceof Array){
            console.log("fire");
            var handlers = this.handlers[type];
            for(var i=0,len=handlers.length; i<len; i++){
                handlers[i](data);
            }
        }
    },

自定义事件的原理利用了堆栈结构,在执行on方法的时候 在自身handlers属性对象内部的相应type存放函数,而在fire的时候按照相应的参数type 来寻找那个数组 并且遍历都触发一遍。

Markdown

样式

样式部分我利用了外联css 我认为利用css比较的方便修改 我的所有class名都使用了wiw_前缀 以保证不和其他DOM冲突

其他

  • 级联 在调用的最后加上return this
  • 模态 在创建弹出窗的时候在其后面加上一个覆盖整个窗口的div
  • 拖动使用jQueryUI 非常方便

总结

组件化毫无疑问是我的未来学习方向,我认为学习组件最重要的是要抛弃以前那种从下往上思考的习惯,应该从抽象的层次思考,然后向下写具体的代码,只有从更高的层次看整个程序,才能写出真正可复用,可维护的代码。

地址 : https://github.com/zhangzhengyi12/require-window