详解Jquery实现ready和bind事件


Posted in Javascript onApril 14, 2016

讲这一节之前,先回顾之前一段代码:

(function (win) {
      var _$ = function (selector, context) {
        return new _$.prototype.Init(selector, context);
      }
      _$.prototype = {
        Init: function (selector, context) {
          this.elements = [];
          var context = context || document;
          if (context.querySelectorAll) {
            var arr = context.querySelectorAll(selector);
            for (var i = 0; i < arr.length; i++) {
              this.elements.push(arr[i]);
            }
          }
          ////这一块是选择器的实现,没有写完,可以自己实现
        },
        each: function (callback) {
          if (this.elements.length > 0) {
            for (var i = 0; i < this.elements.length; i++) {
              callback.call(this, i, this.elements[i]);
            }
          }
        }
      }
      _$.prototype.Init.prototype = _$.prototype;
      window.$ = _$;
    })(window || global);

上面我们实现了节点的查找,今天要讲的是对节点的事件绑定。

熟悉Jquery 源码的TX应该知道:我们上面的代码少了ready事件,只是针对节点进行查询,并没有将document对象考虑进去。我之前单独讲过window.onload和 document. ready的区别,还对document.ready事件进行了扩展。

现在我们把扩展方法加到这里面:

我们的Init方法要改正一下:

Init: function (selector, context) {
          this.elements = [];
          if (typeof selector === "function") {
            this.elements.push(document);
            this.ready(selector);
          }
          else {
            var context = context || document;
            var isDocument = function (ele) {
              var tostring = Object.prototype.toString;
              return tostring.call(ele) == "[object HTMLDocument]" || "[object Document]";
            }
            if (isDocument(selector)) {
              this.elements.push(selector);
            }
            else if (context.querySelectorAll) {
              var arr = context.querySelectorAll(selector);
              for (var i = 0; i < arr.length; i++) {
                this.elements.push(arr[i]);
              }
            }
          }
        }

这段代码的大致意思是:如果传入的参数selector是function类型,就执行ready事件。如果是document就将document对象插入到this.elements数组里面(这个传入之后,会在ready事件里面进行判断)。如果是字符窜,就查询出节点,循环插入到this.elements数组里面,没什么难度。主要考虑到$(document).ready和$(function(){})这两种ready事件的写法。

我们接下来把ready函数加进来:

ready: function (callback) {
          var isDocument = function (ele) {
            var tostring = Object.prototype.toString;
            return tostring.call(ele) == "[object HTMLDocument]" | "[object Document]";
          }
          if (isDocument(this.elements[0])) {
            if (document.addEventListener) {
              document.addEventListener('DOMContentLoaded', function () {
                document.removeEventListener('DOMContentLoaded', arguments.callee, false);
                callback();
              }, false);
            }
            else if (document.attachEvent) {
              document.attachEvent('onreadystatechange', function () {
                if (document.readyState == "complete") {
                  document.detachEvent('onreadystatechange', arguments.callee);
                  callback();
                }
              });
            }
            else if (document.lastChild == document.body) {
              callback();
            }
          }
        }

这段代码我之前其实讲过了(onload和ready的区别),不知道的可以看看。

现在ready事件,我们实现了。然后就可以针对节点进行事件注册了。

我们来实现bind函数,代码如下:

bind: function (type, callback) {
          if (document.addEventListener) {
            this.each(function (i, item) {
              item.addEventListener(type, callback, false);
            });
          }
          else if (document.attachEvent) {
            this.each(function (i, item) {
              item.attachEvent('on' + type, callback);
            });
          }
          else {
            this.each(function (i, item) {
              tem['on' + type] = callback;
            });
          }

        }

这里面都是些兼容性代码,实现节点的事件注册。之前的each,大家可能不知道是要干嘛的。现在在这里面就用到了。

主要作用是针对节点循环做一些操作。

完整代码,来一份:

(function (win) {
      var _$ = function (selector, context) {
        return new _$.prototype.Init(selector, context);
      }
      _$.prototype = {
        Init: function (selector, context) {
          this.elements = [];
          if (typeof selector === "function") {
            this.elements.push(document);
            this.ready(selector);
          }
          else {
            var context = context || document;
            var isDocument = function (ele) {
              var tostring = Object.prototype.toString;
              return tostring.call(ele) == "[object HTMLDocument]" | "[object Document]";
            }
            if (isDocument(selector)) {
              this.elements.push(selector);
            }
            else if (context.querySelectorAll) {
              var arr = context.querySelectorAll(selector);
              for (var i = 0; i < arr.length; i++) {
                this.elements.push(arr[i]);
              }
            }
          }
        },
        each: function (callback) {
          var length = this.elements.length;
          if (length > 0) {
            for (var i = 0; i < length; i++) {
              callback.call(this, i, this.elements[i]);
            }
          }
        },
        ready: function (callback) {
          var isDocument = function (ele) {
            var tostring = Object.prototype.toString;
            return tostring.call(ele) == "[object HTMLDocument]" | "[object Document]";
          }
          if (isDocument(this.elements[0])) {
            if (document.addEventListener) {
              document.addEventListener('DOMContentLoaded', function () {
                document.removeEventListener('DOMContentLoaded', arguments.callee, false);
                callback();
              }, false);
            }
            else if (document.attachEvent) {
              document.attachEvent('onreadystatechange', function () {
                if (document.readyState == "complete") {
                  document.detachEvent('onreadystatechange', arguments.callee);
                  callback();
                }
              });
            }
            else if (document.lastChild == document.body) {
              callback();
            }
          }
        },
        bind: function (type, callback) {
          if (document.addEventListener) {
            this.each(function (i, item) {
              item.addEventListener(type, callback, false);
            });
          }
          else if (document.attachEvent) {
            this.each(function (i, item) {
              item.attachEvent('on' + type, callback);
            });
          }
          else {
            this.each(function (i, item) {
              tem['on' + type] = callback;
            });
          }

        }
      }
      _$.prototype.Init.prototype = _$.prototype;
      window.$ = _$;
    })(window);

这几个函数基本上可以实现对节点的事件注册了。其余的一些特效,还需要扩展。如果感兴趣的话可以自己在  _$.prototype对象里面加方法。

以上就是本文的全部内容,希望能够帮助大家。

Javascript 相关文章推荐
this[] 指的是什么内容 讨论
Mar 24 Javascript
关于JAVASCRIPT urldecode URL解码的问题
Jan 08 Javascript
JavaScript DOM 编程艺术(第2版)读书笔记(JavaScript的最佳实践)
Oct 01 Javascript
封装的jquery翻页滚动(示例代码)
Nov 18 Javascript
JavaScript替换当前页面的方法
Apr 03 Javascript
js实现的二分查找算法实例
Jan 21 Javascript
jQuery基于json与cookie实现购物车的方法
Apr 15 Javascript
使用伪命名空间封装保护独自创建的对象方法
Aug 04 Javascript
AngularJS Ajax详解及示例代码
Aug 17 Javascript
基于JS实现9种不同的面包屑和分布式多步骤导航效果
Feb 21 Javascript
vue element 中的table动态渲染实现(动态表头)
Nov 21 Javascript
详解为什么Vue中的v-if和v-for不建议一起用
Jan 13 Vue.js
一起学写js Calender日历控件
Apr 14 #Javascript
jQuery获取父元素节点、子元素节点及兄弟元素节点的方法
Apr 14 #Javascript
原生js实现autocomplete插件
Apr 14 #Javascript
jQuery循环遍历子节点并获取值的方法
Apr 14 #Javascript
基于jQuery实现音乐播放试听列表
Apr 14 #Javascript
js仿3366小游戏选字游戏
Apr 14 #Javascript
Javascript实现鼠标框选操作  不是点击选取
Apr 14 #Javascript
You might like
PHP实现提取一个图像文件并在浏览器上显示的代码
2012/10/06 PHP
php教程之phpize使用方法
2014/02/12 PHP
php实现的短网址算法分享
2014/06/20 PHP
PHP使用new StdClass()创建空对象的方法分析
2017/06/06 PHP
PHP策略模式定义与用法示例
2017/07/27 PHP
JavaScript URL参数读取改进版
2009/01/16 Javascript
JS 实现双色表格实现代码
2009/11/24 Javascript
用JQUERY增删元素的代码
2012/02/14 Javascript
js/jquery获取浏览器窗口可视区域高度和宽度以及滚动条高度实现代码
2012/12/17 Javascript
JavaScript转换农历类实现及调用方法
2013/01/27 Javascript
jQuery圆形统计图开发实例
2015/01/04 Javascript
JavaScript检测浏览器cookie是否已经启动的方法
2015/02/27 Javascript
JS中捕获console.log()输出的方法
2015/04/16 Javascript
详解javascript new的运行机制
2016/01/26 Javascript
JavaScript实现简单的日历效果
2016/09/25 Javascript
深入探究AngularJs之$scope对象(作用域)
2017/07/20 Javascript
JavaScript递归函数解“汉诺塔”算法代码解析
2018/07/05 Javascript
如何在微信小程序中实现Mixins方案
2019/06/20 Javascript
JavaScript运行机制实例分析
2020/04/11 Javascript
vue基础知识--axios合并请求和slot
2020/06/04 Javascript
Empty test suite.(PyCharm程序运行错误的解决方法)
2018/11/30 Python
python+opencv像素的加减和加权操作的实现
2019/07/14 Python
python线程信号量semaphore使用解析
2019/11/30 Python
python实现逆滤波与维纳滤波示例
2020/02/26 Python
python tqdm库的使用
2020/11/30 Python
很酷的HTML5电子书翻页动画特效
2016/02/25 HTML / CSS
英国最大的自有市场,比亚马逊便宜:Flubit
2019/03/19 全球购物
班组长工作职责
2013/12/25 职场文书
党员创先争优公开承诺书
2014/03/28 职场文书
12.4法制宣传日活动总结
2014/08/26 职场文书
向国旗敬礼活动总结
2014/09/27 职场文书
关于工作经历的证明书
2014/10/11 职场文书
2015秋季开学典礼主持词
2015/07/16 职场文书
学校食堂管理制度
2015/08/04 职场文书
行政后勤人员工作计划应该怎么写?
2019/08/16 职场文书
K8s部署发布Golang应用程序的实现方法
2021/07/16 Golang