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 相关文章推荐
JavaScript 指导方针
Apr 05 Javascript
JavaScript 脚本将当地时间转换成其它时区
Mar 19 Javascript
JavaScript 数组循环引起的思考
Jan 01 Javascript
基于jquery的图片幻灯展示源码
Jul 15 Javascript
浅析js中的浮点型运算问题
Jan 06 Javascript
jQuery实现在textarea指定位置插入字符或表情的方法
Mar 11 Javascript
JS 实现Base64编码与解码实例详解
Nov 07 Javascript
ng2学习笔记之bootstrap中的component使用教程
Mar 09 Javascript
jQuery封装animate.css的实例
Jan 04 jQuery
vue.js项目 el-input 组件 监听回车键实现搜索功能示例
Aug 25 Javascript
Echart折线图手柄触发事件示例详解
Dec 16 Javascript
javascript实现蒙版与禁止页面滚动
Jan 11 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 处理图片的类实现代码
2009/10/23 PHP
php安全之直接用$获取值而不$_GET 字符转义
2012/06/03 PHP
php实现数组纵向转横向并过滤重复值的方法分析
2017/05/29 PHP
PHP实现的注册,登录及查询用户资料功能API接口示例
2017/06/06 PHP
PHP+Ajax实现的博客文章添加类别功能示例
2018/03/29 PHP
php闭包中使用use声明变量的作用域实例分析
2018/08/09 PHP
PHP __call()方法实现委托示例
2019/05/20 PHP
关于laravel 日志写入失败问题汇总
2019/10/17 PHP
ThinkPHP5&amp;5.1实现验证码的生成、使用及点击刷新功能示例
2020/02/07 PHP
PHP 实现链式操作
2021/03/09 PHP
JQuery为textarea添加maxlength属性的代码
2010/04/07 Javascript
jquery中实现简单的tabs插件功能的代码
2011/03/02 Javascript
关于删除时的提示处理(确定删除吗)
2013/11/03 Javascript
js如何判断用户是否是用微信浏览器
2014/06/05 Javascript
Jquery焦点图实例代码
2014/11/25 Javascript
js下拉选择框与输入框联动实现添加选中值到输入框的方法
2015/08/17 Javascript
如何解决谷歌浏览器下jquery无法获取图片的尺寸
2015/09/10 Javascript
AngularJS中$apply方法和$watch方法用法总结
2016/12/13 Javascript
vue实现tab切换外加样式切换方法
2018/03/16 Javascript
JS表格的动态操作完整示例
2020/01/13 Javascript
浅谈vue 二级路由嵌套和二级路由高亮问题
2020/08/06 Javascript
基于js实现的图片拖拽排序源码实例
2020/11/04 Javascript
Python 登录网站详解及实例
2017/04/11 Python
python获取代码运行时间的实例代码
2018/06/11 Python
Python机器学习k-近邻算法(K Nearest Neighbor)实例详解
2018/06/25 Python
详解Python 字符串相似性的几种度量方法
2019/08/29 Python
python多线程分块读取文件
2019/08/29 Python
深入浅析Python 中的sklearn模型选择
2019/10/12 Python
Foot Locker英国官网:美国知名运动产品零售商
2019/02/21 全球购物
英国排名第一的停车场运营商:NCP
2019/08/26 全球购物
写给女生的道歉信
2014/01/08 职场文书
学术会议欢迎词
2014/01/09 职场文书
学习党的群众路线教育实践活动心得体会
2014/03/01 职场文书
2014乡镇干部纪律作风整顿思想汇报
2014/09/13 职场文书
春秋淹城导游词
2015/02/11 职场文书
MySQL创建索引需要了解的
2021/04/08 MySQL