手记

jQuery实战读书笔记(第7章 扩展jQuery)

扩展 jQuery 有两种形式:

  • 直接定义在 $ 上的实用函数

  • 操作 jQuery 包装集的方法

1. jQuery插件开发指南

1.1 为文件和函数命名

  • 为文件名添加jquery前缀

  • 前缀后面是插件的名称

  • 包含插件的主版本号和次版本号(可选项)

  • 以.js结束

1.2 当心 $

(function($){

  //

  // 插件定义

  //

})(jQuery);

1.3 简化参数列表

使用 options 散列值。

例如:complex(valueA, {p7: valueB});

complex(valueA, {

  p3: valueC,

  p4: valueD,

  p7: valueB

});

简化后的函数签名:complex(p1, options)

在函数中,使用 $.extend() 将这些选项与默认值合并:

function complex(p1, options) {

  var settings = $.extend({

    option1: defaultValue1,

    option2: defaultValue2,

    option3: defaultValue3

  }, options || {});

  // 函数其他部分

}

2. 编写自定义实用函数

实用函数是定义为 jQuery($)属性的函数,它不是为了操作DOM元素。

$.say = function(what) { alert('I say ' + what); };

也可以:jQuery.say = function(what) { alert('I say ' + what); };

最安全的写法:

(function($){

  $.say = function(what) { alert('I say ' + what); };

})(jQuery);

2.1 创建数据操作的实用函数

创建这样的实用函数:$.toFixedWidth(value, length, fill)

(function($) {

  $.toFixedWidth = function(value, length, fill) {

    var result = (value || '').toString();

    fill = fill || '0';

    var padding = length - result.length;

    if (padding < 0) {

      result = result.substr(-padding);

    } else {

      for (var n = 0; n < padding; n++)

        result = fill + result;

    }

    return result;

  };

})(jQuery);

为实用函数添加命名空间:

$.jQiaDataFormatter = {};

$.jQiaDataFormatter.toFixedWidth = function(value, length, fill){...};

2.2 编写日期格式器

语法:$.formatDate(date, pattern)

yyyy

yy

MMMM

MMM

MM

M

dd

d

EEEE

EEE

a

HH

H

hh

h

mm

m

ss

s

S

(function($){  $.formatDate = function(date,pattern) {    var result = [];    while (pattern.length>0) {      $.formatDate.patternParts.lastIndex = 0;      var matched = $.formatDate.patternParts.exec(pattern);      if (matched) {        result.push($.formatDate.patternValue[matched[0]].call(this,date));        pattern = pattern.slice(matched[0].length);      }      else {        result.push(pattern.charAt(0));        pattern = pattern.slice(1);      }    }    return result.join('');  };  $.formatDate.patternParts =    /^(yy(yy)?|M(M(M(M)?)?)?|d(d)?|EEE(E)?|a|H(H)?|h(h)?|m(m)?|s(s)?|S)/;  $.formatDate.monthNames = [    'January','February','March','April','May','June','July',    'August','September','October','November','December'  ];  $.formatDate.dayNames = [    'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday',    'Saturday'  ];  $.formatDate.patternValue = {    yy: function(date) {      return $.toFixedWidth(date.getFullYear(),2);    },    yyyy: function(date) {      return date.getFullYear().toString();    },    MMMM: function(date) {      return $.formatDate.monthNames[date.getMonth()];    },    MMM: function(date) {      return $.formatDate.monthNames[date.getMonth()].substr(0,3);    },    MM: function(date) {      return $.toFixedWidth(date.getMonth()+1,2);    },    M: function(date) {      return date.getMonth()+1;    },    dd: function(date) {      return $.toFixedWidth(date.getDate(),2);    },    d: function(date) {      return date.getDate();    },    EEEE: function(date) {      return $.formatDate.dayNames[date.getDay()];    },    EEE: function(date) {      return $.formatDate.dayNames[date.getDay()].substr(0,3);    },    HH: function(date) {      return $.toFixedWidth(date.getHours(),2);    },    H: function(date) {      return date.getHours();    },    hh: function(date) {      var hours = date.getHours();      return $.toFixedWidth(hours>12 ? hours - 12 : hours,2);    },    h: function(date) {      return date.getHours()%12;    },    mm: function(date) {      return $.toFixedWidth(date.getMinutes(),2);    },    m: function(date) {      return date.getMinutes();    },    ss: function(date) {      return $.toFixedWidth(date.getSeconds(),2);    },    s: function(date) {      return date.getSeconds();    },    S: function(date) {      return $.toFixedWidth(date.getMilliseconds(),3);    },    a: function(date) {      return date.getHours() < 12 ? 'AM' : 'PM';    }  };  $.toFixedWidth = function(value,length,fill) {    var result = (value || '').toString();    fill = fill || '0';    var padding = length - result.length;    if (padding < 0) {      result = result.substr(-padding);    }    else {      for (var n = 0; n < padding; n++) result = fill + result;    }    return result;  };})(jQuery);

3. 添加新的包装器方法

创建模式:$.fn.wrapperFunctionName = function(params){ fucntion-body };

示例:

(function($){

  $.fn.makeItblue = function() {

    return this.css('color', 'blue');

  };

})(jQuery);

注意:$.fn 是对象内部 prototype 属性的别名。

警告:包装器主体部分中的函数上下文(this)指向包装集,但是当在这个函数内声明内联函数时,每一个内联函数都有其自己的函数上下文。这时使用 this 要小心!

在定义新的包装器方法时还有一个非常重要的原则:除非要返回特定的值,否则函数应该总是将包装集作为其返回值。这允许新方法参与到任何 jQuery 方法链中。

单独处理每个包装元素的模式:

(function($) {

  $.fn.someNewMethod = function() {

    return this.each(function() {

      //

      // this 指向单个的DOM元素

      //

    });

  };

})(jQuery);

示例:

(function($) {

  $.fn.makeItBlueOrRed = function() {

    return this.each(function() {

      $(this).css('color', $(this).is('[id]') ? 'blue' : 'red');

    });

  };

})(jQuery);

这个例子只是用来演示,实际上可以简化为:

(function($) {

  $.fn.makeItBlueOrRed = function() {

    return this.css('color', function() {

      return $(this).is('[id]') ? 'blue' : 'red');

    });

  };

})(jQuery);

3.1 在包装器方法中应用多个操作

示例:setReadOnly(state) state为true,将文字不透明度设置为0.5表示只读。

(function($){

  $.fn.setReadOnly = function(readonly) {

    return this.filter('input:text')

      .attr('readOnly', readonly)

      .css('opacity', readonly ? 0.5 : 1.0)

      .end();

  };

})(jQuery);

3.2 保留在包装器方法里的状态

方法语法:photomatic(options)

options:

  firstControl

  lastControl

  nextControl

  photoElement

  playControl

  previousControl

  transformer

  delay - 毫秒,默认3000

用法:

$('#thumbnailsPane img').photomatic({

  photoElement: '#photoDisplay',

  previousControl: '#previousButton',

  nextControl: '#nextButton',

  firstControl: '#firstButton',

  lastControl: '#lastButton',

  playControl: '#playButton',

  delay: 1000

});

实现:

(function($){  $.fn.photomatic = function(options) {    var settings = $.extend({      photoElement: 'img.photomaticPhoto',      transformer: function(name) {                     return name.replace(/thumbnail/,'photo');                   },      nextControl: null,      previousControl: null,      firstControl: null,      lastControl: null,      playControl: null,      delay: 3000    },options||{});    function showPhoto(index) {      $(settings.photoElement)        .attr('src',              settings.transformer(settings.thumbnails$[index].src));      settings.current = index;    }    settings.current = 0;    settings.thumbnails$ = this.filter('img');    settings.thumbnails$      .each(        function(n){ $(this).data('photomatic-index',n); }      )      .click(function(){        showPhoto($(this).data('photomatic-index'));      });    $(settings.photoElement)      .attr('title','Click for next photo')      .css('cursor','pointer')      .click(function(){        showPhoto((settings.current+1) % settings.thumbnails$.length);      });    $(settings.nextControl).click(function(){      showPhoto((settings.current+1) % settings.thumbnails$.length);    });    $(settings.previousControl).click(function(){      showPhoto((settings.thumbnails$.length+settings.current-1) %                settings.thumbnails$.length);    });    $(settings.firstControl).click(function(){      showPhoto(0);    });    $(settings.lastControl).click(function(){      showPhoto(settings.thumbnails$.length-1);    });    $(settings.playControl).toggle(      function(event){        settings.tick = window.setInterval(          function(){ $(settings.nextControl).triggerHandler('click'); },          settings.delay);        $(event.target).addClass('photomatic-playing');        $(settings.nextControl).click();      },      function(event){        window.clearInterval(settings.tick);        $(event.target).removeClass('photomatic-playing');      });    showPhoto(0);    return this;  };})(jQuery);

0人推荐
随时随地看视频
慕课网APP