JavaScript插件化开发教程 (三)


Posted in Javascript onJanuary 27, 2015

一,开篇分析

前面两篇文章我们主要讲述了以“jQuery的方式如何开发插件”,以及过程化设计与面向对象思想设计相结合的方式是

如何设计一个插件的,两种方式各有利弊取长补短,本系列文章是以学习为导向的,具体场景大家自己定夺使用方式。那么今天从这篇文章开始,我们就以实例的方式带着大家由浅入深的开发属于自己的插件库。嘿嘿嘿,废话少说,进入正题。直接上实际效果图:

JavaScript插件化开发教程 (三)

大家看到了吧,这是一个选项卡插件,在我们日常做那种单页应用("SPA")的时候或许会接触到,就拿今天的例子来说吧,

我们做一个基于BS结构的系统,会有若干模块组成,它们是构建系统的全部组成,通过这个插件我们可以有效地管理我们模块

的体验形式以及用户可交互性,下面就具体分析一下吧。

(二),实例分析

(1),首先确定这个插件做什么事。下面看一下插件的调用方式,以及配置参数说明。如下代码:

 bigbear.ui.createTab($("#tab"),{

     buttonText : "添加模块" ,

     result : [ 

         {

             text : "向导提示" ,

             url : "help.html" ,

             showClose : "0" ,

             status : "1"

         } ,

         {

             text : "学生信息" ,

             url : "info.html" ,

             showClose : "1" ,

             status : "1"

         } ,

         {

             text : "学生分类" ,

             url : "category.html" ,

             showClose : "1" ,

             status : "1"

         } ,

         {

             text : "大熊君{{bb}}" ,

             url : "bb.html" ,

             showClose : "1" ,

             status : "1"

         } ,

         {

             text : "Beta测试模块" ,

             url : "test.html" ,

             showClose : "1" ,

             status : "1"

         }

     ]

 }) ;

“bigbear.ui.createTab”里面包含两个参数,第一个是dom节点对象,第二个是插件参数选项,"buttonText "代表“Tab“插件中,操作按钮的文字描述。

”result“是一个数组,里面包含的是选项卡项目的属性,包括文字描述,点击选项卡项目时做请求使用的url,”showClose“代表选项卡的选项是否显示关闭按钮。

”status“代表选项的状态,默认为打开状态,可能会有关闭状态,分别表示为:1-打开,0-关闭。

(2),所涉的功能有哪些

通过可选参数,动态生成相关选项条目,如下来个例子:

bigbear.ui.createTab($("#tab"),{

    buttonText : "添加模块" ,

    result : [ 

        {

            text : "jQuery源码分析" ,

            url : "help.html" ,

            showClose : "0" ,

            status : "1"

        } ,

        {

            text : "大熊君{{bb}}}" ,

            url : "bb.html" ,

            showClose : "1" ,

            status : "1"

        }

    ]

}) ;

效果如下所示:

JavaScript插件化开发教程 (三)

可自由添加以及删除条目选项,如下效果所示:

JavaScript插件化开发教程 (三)

上图为其中一种情况,无模块的时候,会提示信息。

JavaScript插件化开发教程 (三)

这是第二种情况,之前删除的可以恢复。

(三),完整代码以供学习,本代码已经过测试,包括目录结构以及相关的文件。

(1),html

<body>

        <div class="dxj-ui-hd">

            大熊君{{bb}} - DXJ UI ------ Tab

        </div>

        <div class="dxj-ui-bd">

            <div id="tab">

                <div class="title">

                    <div class="adder">

                        + 添加学生信息

                    </div>

                    <div class="items">

                        <!--<div><span class="del">X</span>欢迎页</div>

                        <div><span class="del">X</span>用户管理</div>

                        <div><span class="del">X</span>Bigbear</div>-->

                    </div>

                </div>

                <div class="console-panel">

                </div>

                <div class="content">

                    <!--<div class="c">

                        <div class="input-content"><span>姓名:</span><input type="text" /></div>

                        <div class="input-content"><span>备注:</span><textarea></textarea></div>

                    </div>    <div class="input-content"><input type="button" value="保存" /></div>

                    -->

                </div>

            </div>

        </div>

    </body>

(2),css文件代码

.dxj-ui-hd {

    padding:0px ;

    margin : 0 auto;

    margin-top:30px;

    width:780px;

    height:60px;

    line-height: 60px;

    background: #3385ff;

    color:#fff;

    font-family: "微软雅黑" ;

    font-size: 28px;

    text-align: center;

    font-weight:bold;

}

.dxj-ui-bd {

    padding:0px ;

    margin : 0 auto;

    width:778px;

    padding-top : 30px ;

    padding-bottom : 30px ;

    overflow: hidden;

    border:1px solid #3385ff;

}

.dxj-ui-bd #tab {

    padding:0px ;

    margin : 0 auto;

    width:720px;

    overflow: hidden;

}

.dxj-ui-bd #tab .title {

    width:720px;

    overflow: hidden;

    border-bottom:2px solid #3385ff;

}

.dxj-ui-bd #tab .title .adder {

    width:160px;

    height:32px;

    line-height: 32px;

    background: #DC143C;

    color:#fff;

    font-family: "微软雅黑" ;

    font-size: 14px;

    text-align: center;

    font-weight:bold;

    float : left;

    cursor:pointer;

}

.dxj-ui-bd #tab .title .items {

    height:32px;

    margin-left:20px;

    width:540px;

    overflow: hidden;

    float : left;

}

.dxj-ui-bd #tab .title .items div {

    padding:0px;

    margin-left:10px;

    width:96px;

    height:32px;

    line-height: 32px;

    background: #3385ff;

    color:#fff;

    font-family: arial ;

    font-size: 12px;

    text-align: center;

    position:relative;

    float : left;

    cursor:pointer;

}

.dxj-ui-bd #tab .title .items div span.del {

    width:16px;

    height:16px;

    line-height: 16px;

    display:block;

    background: #DC143C;

    position:absolute;

    right:0 ;

    top:0;

    cursor:pointer;

}

.dxj-ui-bd #tab .content {

    width:716px;

    padding-top:30px;

    overflow: hidden;

    border:2px solid #3385ff;

    border-top:0px;

    min-height:130px;

    text-align:center;

}

.dxj-ui-bd #tab .content table {

    margin : 0 auto ;

}

.dxj-ui-bd #tab .content div.c {

    padding-top : 20px ;

    padding-left:20px;

    background:#eee;

    height:140px;

}

.dxj-ui-bd #tab .content div.c .input-content {

    margin-top : 10px ;

    font-family: arial ;

    font-size: 12px;

}

.dxj-ui-bd #tab .console-panel {

    width:716px;

    padding-top:20px;

    padding-bottom:20px;

    overflow: hidden;

    border:2px solid #3385ff;

    border-top:0px;

    border-bottom:2px solid #3385ff;

    background:#fff;

    display:none;

}

.active {

    font-weight:bold ;

}

(3),Js代码如下:

$(function(){

    bigbear.ui.createTab($("#tab"),{

        buttonText : "添加模块" ,

        result : [ 

            {

                text : "向导提示" ,

                url : "help.html" ,

                showClose : "0" ,

                status : "1"

            } ,

            {

                text : "学生信息" ,

                url : "info.html" ,

                showClose : "1" ,

                status : "1"

            } ,

            {

                text : "学生分类" ,

                url : "category.html" ,

                showClose : "1" ,

                status : "1"

            } ,

            {

                text : "大熊君{{bb}}" ,

                url : "bb.html" ,

                showClose : "1" ,

                status : "1"

            } ,

            {

                text : "Beta测试模块" ,

                url : "test.html" ,

                showClose : "1" ,

                status : "1"

            }

        ]

    }) ;

}) ;

(function($){

    var win = window ;

    var bb = win.bigbear = win.bigbear || {

        ui : {}

    } ;

    var ui = bb.ui = {} ;

    var Tab = function(elem,opts){

        this.elem = elem ;

        this.opts = opts ;

    } ;

    var tabProto = Tab.prototype ;

    tabProto._deleteItem = function(item){

        var that = this ;

        this.getElem().find(".title .items div")

        .eq(item["index"])

        .fadeOut(function(){

            that._resetContent() ;

            that._updateStatus(item) ;

            that._triggerItem(item["index"] + 1) ;

            that.getElem().find(".title .adder").trigger("click") ;

        }) ;

    } ;

    tabProto._triggerItem = function(next){

        var nextStatus = this._getStatus(next) ;

        var items = this.getElem().find(".title .items div") ;

        next = items.eq(next) ;

        if(next.size() && "1" == nextStatus){ //后继dom节点存在

            next.trigger("click") ;

        }

        else{

            items.eq(0).trigger("click") ;

        }

    } ;

    tabProto._getStatus = function(index){

        var status = "" ;

        $.each(this.getOpts()["result"],function(i,item){

            if(index == item["index"]){

                status += item["status"] ;

                return false ;

            }

        }) ;

        return status ;

    } ;

    tabProto._updateStatus = function(item){

        var status = item["status"] ;

        item["status"] = ("1" == status) ? "0" : "1" ;

    } ;

    tabProto.init = function(){

        var that = this ;

        this.getElem().find(".title .adder")

        .text("+" + this.getOpts()["buttonText"])

        .on("click",function(){

            that._toggleConsolePanel(function(){

                var root = that.getElem().find(".console-panel").empty() ;

                $.each(that.getOpts()["result"],function(i,item){

                    if("0" == item["status"]){

                        var elem = $("<div style='float:left';></div>")

                        .data("item",item)

                        .appendTo(root) ;

                        $("<input type='radio' name='addmod' />").appendTo(elem) ;

                        $("<span></span>").text(item["text"]).appendTo(elem) ;

                    }

                }) ;

                if(root.find("div").size()){

                    $("<input type='button' value='添加模块' style='margin-left:20px'/>")

                    .on("click",function(){

                        var data = root.find("input[type=radio]:checked").parent().data("item") ;

                        that._updateStatus(data) ;

                        that.getElem().find(".title .items div").eq(data["index"]).fadeIn().trigger("click") ;

                        that.getElem().find(".title .adder").trigger("click") ;

                    })

                    .appendTo(root) ;

                }

                else{

                    root.text("暂无任何可添加的项目!") ;

                }

            }) ;

        }) ;

        $.each(this.getOpts()["result"],function(i,item){

            item["index"] = i ;

            that._render(item) ;

        }) ;

        this.getElem().find(".title .items div")

        .eq(0)

        .trigger("click") ; // 假定是必须有一项,否则插件意义就不大了!

    } ;

    tabProto._toggleConsolePanel = function(callback){

        this.getElem().find(".console-panel").slideToggle(function(){

            $.isFunction(callback) && callback() ;

        }) ;

    } ;

    tabProto._resetContent = function(){

        this.getElem().find(".content").html("") ;

    } ;

    tabProto._setContent = function(html){

        this.getElem().find(".content").html(html) ;

    } ;

    tabProto._getContent = function(url){

        return $.ajax({

            url : url

        }) ;

    } ;

    tabProto._render = function(data){

        var that = this ;

        var item = $("<div></div>")

        .text(data["text"])

        .on("click",function(){

            that._setCurrent(data["index"]) ;

            that._getContent(data["url"]).done(function(result){

                that._setContent(result) ;

            })

            .fail(function(){

                throw new Error("Net Error !") ;

            });

        })

        .appendTo(this.getElem().find(".title .items")) ;

        if("1" == data["showClose"]){

            $("<span class='del'>X</span>")

            .on("click",function(){

                if(win.confirm("是否删除此项?")){

                    that._deleteItem(data) ;

                    return false ; // 阻止冒泡

                }

            })

            .appendTo(item) ;

        } 

    } ;

    tabProto._setCurrent = function(index){

        var items = this.getElem().find(".title .items div").removeClass("active") ;

        items.eq(index).addClass("active") ;

        var contents = this.getElem().find(".content .c").hide() ;

        contents.eq(index).show() ;

    } ;    

    tabProto.getElem = function(){

        return this.elem ;

    } ;

    tabProto.getOpts = function(){

        return this.opts ;

    } ;

    ui.createTab = function(elem,opts){

        var tab = new Tab(elem,opts) ;

        tab.init() ;

        return tab ;

    } ;        

})(jQuery) ;

(四),最后总结

(1),面向对象的思考方式合理分析功能需求。

(2),以类的方式来组织我们的插件逻辑。

(3),不断重构上面的实例,如何进行合理的重构那?不要设计过度,要游刃有余,推荐的方式是过程化设计与面向对象思想设计相结合。

    (4),思考一下上面例子中,选项卡中的选项是否可以独立成单独的类那?比如“Item”,那么“Tab”类如何修改那?带着问题去思考吧。。。

以上就是本文的全部内容了,后续我们将继续完善此插件,喜欢本文的话,来给点个赞吧。

Javascript 相关文章推荐
js中if语句的几种优化代码写法
Mar 12 Javascript
jquerydom对象的事件隐藏显示和对象数组示例
Dec 10 Javascript
js遍历map javaScript遍历map的简单实现
Aug 26 Javascript
JS正则匹配中文的方法示例
Jan 06 Javascript
详解vue组件化开发-vuex状态管理库
Apr 10 Javascript
用js实现before和after伪类的样式修改的示例代码
Sep 07 Javascript
JS基于开关思想实现的数组去重功能【案例】
Feb 18 Javascript
webpack4之如何编写loader的方法步骤
Jun 06 Javascript
基于Node.js的大文件分片上传示例
Jun 19 Javascript
微信小程序的授权实现过程解析
Aug 02 Javascript
layui输入框只允许输入中文且判断长度的例子
Sep 18 Javascript
JS实现简易日历效果
Jan 25 Javascript
js实现简单随机抽奖的方法
Jan 27 #Javascript
JavaScript插件化开发教程 (二)
Jan 27 #Javascript
javascript将数字转换整数金额大写的方法
Jan 27 #Javascript
JS实现同时搜索百度和必应的方法
Jan 27 #Javascript
js获取域名的方法
Jan 27 #Javascript
JavaScript插件化开发教程 (一)
Jan 27 #Javascript
js的toLowerCase方法用法实例
Jan 27 #Javascript
You might like
PHP实现的文件操作类及文件下载功能示例
2016/12/24 PHP
PHP通过文件保存和更新信息的方法分析
2019/09/12 PHP
jquery获取子节点和父节点的示例代码
2013/09/10 Javascript
文本框回车提交与禁止提交示例
2013/09/27 Javascript
基于jquery自定义的漂亮单选按钮RadioButton
2013/11/19 Javascript
js获取日期:昨天今天和明天、后天
2014/06/11 Javascript
jQuery实现返回顶部功能适合不支持js的浏览器
2014/08/19 Javascript
深入探讨javascript中的数据类型
2015/03/04 Javascript
jQuery统计指定子元素数量的方法
2015/03/17 Javascript
深入理解JavaScript中的并行处理
2016/09/22 Javascript
Jquery Easyui搜索框组件SearchBox使用详解(19)
2016/12/17 Javascript
jquery动态添加带有样式的HTML标签元素方法
2018/02/24 jQuery
vue-cli脚手架config目录下index.js配置文件的方法
2018/03/13 Javascript
elementUI select组件默认选中效果实现的方法
2019/03/25 Javascript
js常用正则表达式集锦
2019/05/17 Javascript
微信小程序实现电子签名并导出图片
2020/05/27 Javascript
基于Python实现文件大小输出
2016/01/11 Python
Python每天必学之bytes字节
2016/01/28 Python
python解决汉字编码问题:Unicode Decode Error
2017/01/19 Python
python 将字符串转换成字典dict的各种方式总结
2018/03/23 Python
Python3之不使用第三方变量,实现交换两个变量的值
2019/06/26 Python
修改 CentOS 6.x 上默认Python的方法
2019/09/06 Python
Pytest mark使用实例及原理解析
2020/02/22 Python
基于Python爬虫采集天气网实时信息
2020/06/05 Python
Keras构建神经网络踩坑(解决model.predict预测值全为0.0的问题)
2020/07/07 Python
Python实现PS滤镜中的USM锐化效果
2020/12/04 Python
HTML5 embed标签定义和用法详解
2014/05/09 HTML / CSS
英国最大的线上保健品零售商之一:Vitamin Planet
2016/12/01 全球购物
西班牙购买隐形眼镜、眼镜和太阳镜网站:Lentiamo.es
2020/06/11 全球购物
电信专业毕业生推荐信
2013/11/18 职场文书
情人节寄语大全
2014/04/11 职场文书
2014年世界艾滋病日演讲稿
2014/11/28 职场文书
个人自荐书怎么写
2015/03/26 职场文书
最新农村养殖致富:资金投入较低的创业项目有哪些?
2019/09/26 职场文书
开发者首先否认《遗弃》被取消的传言
2022/04/11 其他游戏
二维码条形码生成的JavaScript脚本库
2022/07/07 Javascript