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 清空File控件的路径值
Jul 08 Javascript
JS生成不重复随机数组的函数代码
Jun 10 Javascript
Javascript基础教程之switch语句
Jan 18 Javascript
JavaScript按值删除数组元素的方法
Apr 24 Javascript
jQuery+css实现的切换图片功能代码
Jan 27 Javascript
详解Angular2中的编程对象Observable
Sep 17 Javascript
Angularjs实现多图片上传预览功能
Jul 18 Javascript
Vue.js更改调试地址端口号的实例
Sep 19 Javascript
axios实现简单文件上传功能
Sep 25 Javascript
element el-tree组件的动态加载、新增、更新节点的实现
Feb 27 Javascript
vue-drag-chart 拖动/缩放图表组件的实例代码
Apr 10 Javascript
原生js实现自定义滚动条组件
Jan 20 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实现删除字符串中任何字符的函数
2015/08/11 PHP
PHP中类的继承和用法实例分析
2016/05/24 PHP
php实现的二分查找算法示例
2017/06/20 PHP
laravel5.1框架model类查询的实现方法
2019/10/08 PHP
javascript中有趣的反柯里化深入分析
2012/12/05 Javascript
nodejs中使用多线程编程的方法实例
2015/03/24 NodeJs
nodejs开发微博实例
2015/03/25 NodeJs
JQuery分屏指示器图片轮换效果实例
2015/05/21 Javascript
深入浅析NodeJs并发异步的回调处理
2015/12/21 NodeJs
非常漂亮的相册集 使用jquery制作相册集
2016/04/28 Javascript
jQuery使用正则表达式限制文本框只能输入数字
2016/06/18 Javascript
JS遍历对象属性的方法示例
2017/01/10 Javascript
详解微信开发中snsapi_base和snsapi_userinfo及静默授权的实现
2017/03/11 Javascript
详解微信小程序 template添加绑定事件
2017/06/23 Javascript
JS实现中文汉字按拼音排序的方法
2017/10/09 Javascript
vue使用localStorage保存登录信息 适用于移动端、PC端
2019/05/27 Javascript
JS如何调用WebAssembly编译出来的.wasm文件
2020/11/05 Javascript
python转换摩斯密码示例
2014/02/16 Python
利用Fn.py库在Python中进行函数式编程
2015/04/22 Python
神经网络python源码分享
2017/12/15 Python
使用tensorflow DataSet实现高效加载变长文本输入
2020/01/20 Python
python orm 框架中sqlalchemy用法实例详解
2020/02/02 Python
python根据用户需求输入想爬取的内容及页数爬取图片方法详解
2020/08/03 Python
python3中TQDM库安装及使用详解
2020/11/18 Python
python制作一个简单的gui 数据库查询界面
2020/11/19 Python
绢花、人造花和人造花卉:BLOOM
2019/08/07 全球购物
时尚孕妇装:HATCH Collection
2019/09/24 全球购物
耐克亚太地区:Nike APAC
2019/12/07 全球购物
Java里面如何把一个Array数组转换成Collection, List
2013/07/26 面试题
大学中国梦演讲稿
2014/04/23 职场文书
事业单位考核材料
2014/05/21 职场文书
实习护士自荐信
2014/06/21 职场文书
王金山在党的群众路线教育实践活动总结大会上的讲话稿
2014/10/25 职场文书
幼儿园门卫安全责任书
2015/05/08 职场文书
mysql在项目中怎么选事务隔离级别
2021/05/25 MySQL
使用Python通过企业微信应用给企业成员发消息
2022/04/18 Python