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 相关文章推荐
[全兼容哦]--实用、简洁、炫酷的页面转入效果loing
May 07 Javascript
用XMLDOM和ADODB.Stream实现base64编码解码实现代码
Nov 28 Javascript
改善用户体验的五款jQuery插件分享
May 22 Javascript
JQuery入门——用bind方法绑定事件处理函数应用介绍
Feb 05 Javascript
分享javascript计算时间差的示例代码
Mar 19 Javascript
JavaScript基础——使用Canvas绘图
Nov 02 Javascript
Vue.js通用应用框架-Nuxt.js的上手教程
Dec 25 Javascript
layer弹出层自适应高度,垂直水平居中的实现
Sep 16 Javascript
Vue路由管理器Vue-router的使用方法详解
Feb 05 Javascript
JavaScript实现PC端四格密码输入框功能
Feb 19 Javascript
vue treeselect获取当前选中项的label实例
Aug 31 Javascript
vue+iview实现文件上传
Nov 17 Vue.js
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 防止单引号,双引号在接受页面转义
2008/07/10 PHP
php压缩HTML函数轻松实现压缩html/js/Css及注意事项
2013/01/27 PHP
解析isset与is_null的区别
2013/08/09 PHP
Linux下PHP安装mcrypt扩展模块笔记
2014/09/10 PHP
php判断当前用户已在别处登录的方法
2015/01/06 PHP
thinkPHP框架可添加js事件的分页类customPage.class.php完整实例
2017/03/16 PHP
PHP框架实现WebSocket在线聊天通讯系统
2019/11/21 PHP
主页面中的两个iframe实现鼠标拖动改变其大小
2013/04/16 Javascript
js 判断图片是否加载完以及实现图片的预下载
2014/08/14 Javascript
JavaScript匿名函数用法分析
2015/02/13 Javascript
Javascript中的匿名函数与封装介绍
2015/03/15 Javascript
Webpack 实现 AngularJS 的延迟加载
2016/03/02 Javascript
Angularjs整合微信UI(weui)
2016/03/15 Javascript
JavaScript实现页面定时刷新(定时器,meta)
2016/10/12 Javascript
JS创建对象的写法示例
2016/11/04 Javascript
js HTML5 canvas绘制图片的方法
2017/09/08 Javascript
基于JavaScript中字符串的match与replace方法(详解)
2017/12/04 Javascript
Angular实现较为复杂的表格过滤,删除功能示例
2017/12/23 Javascript
基于Bootstrap下拉框插件bootstrap-select使用方法详解
2018/08/07 Javascript
vue 弹框产生的滚动穿透问题的解决
2018/09/21 Javascript
Element Badge标记的使用方法
2020/07/27 Javascript
JS实现炫酷雪花飘落效果
2020/08/19 Javascript
跟老齐学Python之总结参数的传递
2014/10/10 Python
Python 2.7.x 和 3.x 版本的重要区别小结
2014/11/28 Python
Python何时应该使用Lambda函数
2019/07/02 Python
通过selenium抓取某东的TT购买记录并分析趋势过程解析
2019/08/15 Python
linux面试相关问题
2012/08/11 面试题
土木工程专业个人求职信
2013/12/05 职场文书
感恩寄语大全
2014/04/11 职场文书
通信工程求职信
2014/07/16 职场文书
小学生十佳少年事迹材料
2014/08/20 职场文书
机关干部三严三实心得体会
2014/10/13 职场文书
学习心理学的体会
2014/11/07 职场文书
爱国主义主题班会
2015/08/14 职场文书
竞聘开场白方式有哪些?
2019/08/28 职场文书
分析JVM源码之Thread.interrupt系统级别线程打断
2021/06/29 Java/Android