最近在学前端框架amazeui,之前用其中的CSS样式搭建了一个伪360网页,学会了点布局的东西,但是始终觉得有点无聊。所以这几天就开始研究jquery代码了。

对于我这样一个初学者来说,有很多东西都只能用懵逼来形容,比如我看到这么一段代码(复制自amazeui):



var checkin = $myStart2.datepicker({
      onRender: function(date, viewMode) {
        // 默认 days 视图,与当前日期比较
        var viewDate = nowDay;

        switch (viewMode) {
          // moths 视图,与当前月份比较
          case 1:
            viewDate = nowMoth;
            break;
          // years 视图,与当前年份比较
          case 2:
            viewDate = nowYear;
            break;
        }

        return date.valueOf() < viewDate ? 'am-disabled' : '';
      }
    }).on('changeDate.datepicker.amui', function(ev) {
        if (ev.date.valueOf() > checkout.date.valueOf()) {
          var newDate = new Date(ev.date)
          newDate.setDate(newDate.getDate() + 1);
          checkout.setValue(newDate);
        }
        checkin.close();
        $('#my-end-2')[0].focus();
    }).data('amui.datepicker');



看这里面的写法,简单的来说就是:



var checkin = $mystart2.datapicker().on().data();



我一开始是以类调用方法来理解的,即datapicker()里面包含了on()这个方法,on()里面包含了data()这个方法。。。

后来想了一下,不太对呀,on()是一个监听事件,应该是对任意一个控件就可以使用的,哪来那么复杂的继承什么的。。。

那这莫非是 -- 同时调用多个方法?好吧,我把代码改了一下,效果是一样的:



datepicker1 = $myStart2.datepicker({  //设置日期
            // datepicker1生成了一份日历
            onRender: function(date, viewMode) {
                // onRender是一个方法,其在日历生成后触发,用以渲染
                // 传递所设定的日期,以及viewMode -- 0,1,2分别表示日月年
                // 默认 days 视图,与当前日期比较
                var viewDate = nowDay;

                switch (viewMode) {
                    // moths 视图,与当前月份比较
                    case 1:
                        viewDate = nowMoth;
                        break;
                    // years 视图,与当前年份比较
                    case 2:
                        viewDate = nowYear;
                        break;
                }

                return date.valueOf() < viewDate ? 'am-disabled' : '';
                // 对每一个日期都作判断,设定其状态是disable或者able
            }
        })
        datepicker1.on('changeDate.datepicker.amui', function(ev) {   /*设置日期结束赋值后的动作*/
            if (ev.date.valueOf() > checkout.date.valueOf()) {
                var newDate = new Date(ev.date)
                newDate.setDate(newDate.getDate() + 1);
                checkout.setValue(newDate);   /*禁用日期必须比设置日期多一天*/
            }
            checkin.close();
            $('#my-end-2')[0].focus();   /*聚焦到禁用日期上*/
        })
        var checkin = datepicker1.data('amui.datepicker');  // 所设置的具体日期



也就是说,第一段代码干了三件事情:

1. 初始化了日历datapicker();

2. 用了onRender来渲染了datapicker;

3. 把日历中选中的具体日期赋给了checkin。

也就是说,这三个方法,其实只是写在一起而已,没有什么血缘关系。。JS代码原来可以这么任性- -,好吧我一个初学者确实水平不够。

然后我还有第二个问题。。。。这个叫做datapicker的类中,写法是这样的:



XX.datapicker({
   onRender: function(data,  viewMode){
           ........
           return XX;
    } 
})



这种写法好猎奇,仔细一看的话会发现,如果onRender是datapicker中的一个方法,那么不应该写成:datapicker.onRender(data, viewMode)之类的吗?

后来我去看了一下jQuery UI关于datapicker的描述,发现里面有一些方法是这样的:



onClose : function(dateText, inst)
    当日期面板关闭后触发此事件(无论是否有选择日期),参数为选择的日期和当前日期插件的实例。
    初始:$('.selector').datepicker({ onClose: function(dateText, inst) { ... } });



原来如此,也就是说,上面的onRender也是一个触发事件,虽然AMUI官方没有讲,我的理解就是,当日历初始化后出发onRender事件,它会把日历上所有的日期都作为参数传递给function(),然后对每个日期进行判断,如果是禁止日期,则返回值“am-disabled”,从而将该日期变成不可选择,否则返回空,即该日期可以选择,这样就可以实现对部分日期的禁用。

至于这个返回值是怎么作用到datapicker上的,我现在也还没搞懂的说。。。。

另外还有关于绑定时间on('event', function(variable))这种jquery中最经典的用法,举个amazeui中的例子:



$('#my-start').datepicker().on('changeDate.datepicker.amui', function(event) {    /*'changeDate.datepicker.amui'触发返回event参数,内含date成员可提取日期信息*/
            if (event.date.valueOf() > endDate.valueOf()) {
                $alert.find('p').text('开始日期应小于结束日期!').end().show();
            } else {
                $alert.hide();
                startDate = new Date(event.date);
                $('#my-startDate').text($('#my-start').data('date'));  /*把日历控件选择的时间赋值到text中显示*/
            }
            $(this).datepicker('close');   /*日期选择完后关闭日历控件*/
        });



注释里面已经说明了,当日期改变时,这段代码就会被触发,然后会把时间参数,即event传递给function,这样就可以获取到事件发生时的相关信息。

今天还看了一下所谓的类创建方法(参考了)



function People(name)
    {
        this.name=name;
//对象方法
        this.Introduce=function(){
            alert("My name is "+this.name);
        }
    }
    //类方法
    People.Run=function(){
        alert("I can run");
    }
    //原型方法
    People.prototype = {
        IntroduceChinese :function () {  /*增加IntroduceChinese这个方法*/
        /*        prototype本质上是对类的克隆,但是不会克隆同名函数
        若需要调用其克隆母体的同名函数,则需要实例化类后,用call函数来调用*/
            alert("我的名字是" + this.name);
        },

        IntroduceDirtyWord: function(){
            alert("在下坂本,有何贵干!");
        }
    }

    //测试

    var p1=new People("Windking");

    p1.Introduce();

    People.Run();

    p1.IntroduceChinese();

    p1.IntroduceDirtyWord();



 

这段代码其实说了很多问题:

1. 类方法与对象方法。如Run()是类方法,而IntroduceChinese()是对象方法。

2. prototype的用法,prototype返回的是对象原型类型的引用,也就是说 A.Prototype = new B() 是把B中的所有方法和属性都克隆给了A。在代码例子中,我们使用的是A.Prototype = {method1:function(){}, method2:function(){}}这样的语法,其实也就拓展了A的方法,因此People的实例p1中拥有了通过prototype定义的方法。