zoukankan      html  css  js  c++  java
  • javascript的MVC三层架构(案例之分页插件)

    javascript的MVC三层架构(案例之分页插件)

    作者:田想兵 博客地址:http://www.cnblogs.com/tianxiangbing

    最近很少写博文,一是比较忙,二是没啥心情,好,言归正传,今天的主题是MVC版的javascript结构,做程序的,可能对MVC会有较深刻的印象,就是Model-View-Control,中文的意思就是模型-视图-控制器,这好像已经是一个很成熟的结构了,后来又有些在它基础上的拓展,有兴趣的可以摆渡一下。所以它基本上适应任何情况下的编程,今天我们就要用它来实现js版的一个分页控件。

    首先,我们先明确每一层是做什么的:

    View也就是视图层,在这里面我们会去初始化一些html元素;

    Model模型层,我一直认为这一层存在的意义不大,因为通常我们new一个js对象的时候,都会初始化它的一些变量,很少会去单独写个方法去设置它,所以就把Model改成发送ajax请求了;

    Control控制器,这里就是一些业务逻辑了,这里我们可以再分出一个事件层来;

    Event事件层,处理html事件。

    中途停了一天,接着写,不知道为啥,最近一直都没有办法集中精力,可能是因为儿童节吧,今天还要加班, 可悲的码农啊,题外话不说了,继续码字。

    现在我们来分析下需求,分页控件,无非就是对数据的一个分组显示,所以它一定会有pagesize(每页条数)和count(总条数) 这两个属性,当然也有人喜欢把所有数据返回过来给前端来分页,不过分页的目的之一,就是为了减轻数据量,一次批量返回也不是不行,具体情况具体分析吧!有了count和pagesize后,我们就可以算出总页码数了。

    parseInt( count % pageSize >0 ?count / pageSize+1:count/pagesize)

    这个很简单,就是整除有余的话就多一页,否则取整数部分。

    我们先看下效果图,不然的话,脑子里没有一个结构,也是无法下手的。请观看下图:

     

    接着该MVC三层结构出场了,我们先在view(视图层)初始化一些必要的HTML元素:

    view:function(method,args){        
            var _self=this;    
            var _class={
                page:function(args){
                    var _html='\
                            <div class="pager">\
                                <a class="firstPage" href="javascript:void(0);">首页</a>\
                                <a class="prePage" href="javascript:void(0);">上一页</a>\
                                <span class="inputPage">第<input type="text" value="'+ _self.currentIndex +'" class="txt_curIndex" name="txt_curIndex"/>页/<i>'+_self.sumPage+'</i>页</span>\
                                <a class="nextPage" href="javascript:void(0);">下一页</a>\
                                <a class="lastPage" href="javascript:void(0);">末页</a>\
                            </div>\
                                ';
                    _self.content.html(_html);
                    _self.event("bind",args);
                }
            };
            return _class[method](args);
        }

     在这里,我又调用了事件层,来给这些HTML元素绑定相应的事件,这里大概有五个事件,就是上一页,下一页,首页,未页,及跳转。这些事件,其本质就是改变页码数,好,那我们就写个请求页码数的方法:

    model:function(method,args){
            var _self=this;
            var _class={
                go:function(args){
                    return $.ajax({
                        url:_self.ajaxUrl,
                        dataType:"json",
                        async:true,
                        data:args[0],
                        success:function(data){
                            args[1](data);
                            _self.cpu("change",data);
                        },
                        type:"GET",
                        error:function(data){
                             alert("json格式不正确")
                        }
                    });
                }
            };
            return _class[method](args);
        }

    这是个ajax请求,放在model层下面,有两个参数,一个是ajax需要传的参数{page:1} args[0],另一个是外部的一个回调方法,用来格式化内容的,这个跟分页控件没有半毛钱关系,所以就当作回调。好,接着我们在控制器层里就调用这个方法就行了,刚才说到有五个事件,这样就对应了五个控制器:

    View Code
        cpu:function(method,args){
            var _self=this;
            var _class={
                change:function(data){
                    var arr = data;
                    if (data.count>0){
                        _self.count=data.count;
                        _self.sumPage= parseInt( _self.count % _self.pageSize >0 ? _self.count / _self.pageSize+1 : _self.count / _self.pageSize);
                        _self.view("page");
                    }
                },                
                jump:function(args){
                    var input = parseInt($("[name='txt_curIndex']",_self.content).val());
                    if (input>0 && input <= _self.sumPage){
                        _self.currentIndex = input;
                        _self.ajaxArgs.page = _self.currentIndex-1;
                        _self.model("go",[_self.ajaxArgs,_self.returnFunc]);
                    }
                },
                prev:function(args){
                    if (_self.currentIndex > 1){
                        _self.currentIndex--;
                        $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                        _self.cpu("jump",args);
                    }
                },
                next:function(args){                
                    if (_self.currentIndex < _self.sumPage - 1){
                        _self.currentIndex++;
                        $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                        _self.cpu("jump",args);
                    }
                },
                last:function(args){
                    _self.currentIndex = _self.sumPage;
                    $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                    _self.cpu("jump",args);
                },
                first:function(args){
                    _self.currentIndex = 1;
                    $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                    _self.cpu("jump",args);
                }
            };
            return _class[method](args);
        }
    };

     数一数,是不是五个,我勒个去,作者数学不好,竟然是他妹的六个,竟然多了个change,好啦,把chage这个放model里去吧,他的作用就是计算一些变量的值。

    最后事件层只需要调用Control控制层相对应的方法就行了:

        event:function(method,args){
            var _self=this;
            var pager = $("div.pager",_self.content);
            var _class={
                bind:function(args){
                    $("[name='txt_curIndex']",_self.content).keydown(function(e){
                        if (e.keyCode==13){
                            _self.cpu("jump",args);
                        }
                    });
                    $(".prePage",_self.content).click(function(){
                        _self.cpu("prev",args);
                    });    
                    $(".nextPage",_self.content).click(function(){
                        _self.cpu("next",args);
                    });
                    $(".lastPage",_self.content).click(function(){
                        _self.cpu("last",args);
                    });
                    $(".firstPage",_self.content).click(function(){
                        _self.cpu("first",args);
                    });
                }
            };
            return _class[method](args);
        },

    这样是不是就完了呢,你猜?没错,恭喜你,猜对了,还没有结束,因为我们还没有看到入口,一般情况我们都喜欢定义一个名为init的方法来初始化,这次的情况也很一般,所以定义init吧:

    init:function(ops){
            var _self = this;
            _self.currentIndex = ops.currentIndex;
            _self.ajaxArgs = $.extend( ops.ajaxArgs,{page:this.currentIndex-1});
            _self.model("go",[_self.ajaxArgs,_self.returnFunc]);
        },

    整个分页插件的代码如下:

    View Code
    function Pager(ops){
        this.currentIndex = 1;
        this.count = ops.count;
        this.pageSize = ops.pageSize||10;
        this.sumPage = 1;
        this.content = ops.content;
        this.ajaxUrl = ops.url;
        this.returnFunc=ops.returnFunc||new Function();
    };
    Pager.prototype={
        init:function(ops){
            var _self = this;
            _self.currentIndex = ops.currentIndex;
            _self.ajaxArgs = $.extend( ops.ajaxArgs,{page:this.currentIndex-1});
            _self.model("go",[_self.ajaxArgs,_self.returnFunc]);
        },
        view:function(method,args){        
            var _self=this;    
            var _class={
                page:function(args){
                    var _html='\
                            <div class="pager">\
                                <a class="firstPage" href="javascript:void(0);">首页</a>\
                                <a class="prePage" href="javascript:void(0);">上一页</a>\
                                <span class="inputPage">第<input type="text" value="'+ _self.currentIndex +'" class="txt_curIndex" name="txt_curIndex"/>页/<i>'+_self.sumPage+'</i>页</span>\
                                <a class="nextPage" href="javascript:void(0);">下一页</a>\
                                <a class="lastPage" href="javascript:void(0);">末页</a>\
                            </div>\
                                ';
                    _self.content.html(_html);
                    _self.event("bind",args);
                }
            };
            return _class[method](args);
        },
        event:function(method,args){
            var _self=this;
            var pager = $("div.pager",_self.content);
            var _class={
                bind:function(args){
                    $("[name='txt_curIndex']",_self.content).keydown(function(e){
                        if (e.keyCode==13){
                            _self.cpu("jump",args);
                        }
                    });
                    $(".prePage",_self.content).click(function(){
                        _self.cpu("prev",args);
                    });    
                    $(".nextPage",_self.content).click(function(){
                        _self.cpu("next",args);
                    });
                    $(".lastPage",_self.content).click(function(){
                        _self.cpu("last",args);
                    });
                    $(".firstPage",_self.content).click(function(){
                        _self.cpu("first",args);
                    });
                }
            };
            return _class[method](args);
        },
        model:function(method,args){
            var _self=this;
            var _class={
                go:function(args){
                    return $.ajax({
                        url:_self.ajaxUrl,
                        dataType:"json",
                        async:true,
                        data:args[0],
                        success:function(data){
                            args[1](data);
                            _self.model("change",data);
                        },
                        type:"GET",
                        error:function(data){
                        console.dir(data)
                             alert("json格式不正确")
                        }
                    });
                },
                change:function(data){
                    var arr = data;
                    if (data.count>0){
                        _self.count=data.count;
                        _self.sumPage= parseInt( _self.count % _self.pageSize >0 ? _self.count / _self.pageSize+1 : _self.count / _self.pageSize);
                        _self.view("page");
                    }
                }
            };
            return _class[method](args);
        },
        cpu:function(method,args){
            var _self=this;
            var _class={                
                jump:function(args){
                    var input = parseInt($("[name='txt_curIndex']",_self.content).val());
                    if (input>0 && input <= _self.sumPage){
                        _self.currentIndex = input;
                        _self.ajaxArgs.page = _self.currentIndex-1;
                        _self.model("go",[_self.ajaxArgs,_self.returnFunc]);
                    }
                },
                prev:function(args){
                    if (_self.currentIndex > 1){
                        _self.currentIndex--;
                        $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                        _self.cpu("jump",args);
                    }
                },
                next:function(args){                
                    if (_self.currentIndex < _self.sumPage - 1){
                        _self.currentIndex++;
                        $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                        _self.cpu("jump",args);
                    }
                },
                last:function(args){
                    _self.currentIndex = _self.sumPage;
                    $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                    _self.cpu("jump",args);
                },
                first:function(args){
                    _self.currentIndex = 1;
                    $("[name='txt_curIndex']",_self.content).val(_self.currentIndex);
                    _self.cpu("jump",args);
                }
            };
            return _class[method](args);
        }
    };

    OK,最后我们回过头来看下,这个结构的优劣点,优点了,就是更方便于扩展,可以无限制的往下加,层次分得较清明,劣点是,层次过深,效率会低一些,而且看着不爽,所以我给他定位为,管理系统业务逻辑较多时使用,一般的JS效果插件还是使用扁平结构的好。今天就写到这吧,谢谢您的观看,最后的台词是:如果你有任何的疑问都不要来问我,请反复阅读本文。也可以加入我的QQ群与其他人讨论,本文的DEMO会放在群共享里。我的群号有5678537,70210212,闭幕.

  • 相关阅读:
    最优比率环 SPFA+二分
    严格次小生成树
    SPFA判断负环BFS+DFS
    poj 1149 PIGS 网络流-最大流 建图理解
    9.20开始的停课日常
    Speed
    [BZOJ4827][Hnoi2017]礼物(FFT)
    中山纪念中学集训日志
    [POJ1151][HDU1542]Atlantis(线段树,扫描线)
    [BZOJ2002][洛谷P3203][Hnoi2010]Bounce 弹飞绵羊(LCT维护链长)
  • 原文地址:https://www.cnblogs.com/tianxiangbing/p/js_mvc.html
Copyright © 2011-2022 走看看