详解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 相关文章推荐
限制文本字节数js代码
Mar 06 Javascript
11款基于Javascript的文件管理器
Oct 25 Javascript
详谈 Jquery Ajax异步处理Json数据.
Sep 09 Javascript
jQuery代码优化之基本事件
Nov 01 Javascript
JavaScript 动态加载脚本和样式的方法
Apr 13 Javascript
特殊日期提示功能的实现方法
Jun 16 Javascript
基于jQuery实现页面搜索功能
Mar 26 Javascript
jQuery遮罩层实例讲解
May 11 jQuery
react router 4.0以上的路由应用详解
Sep 21 Javascript
使用weixin-java-tools完成微信授权登录、微信支付的示例
Sep 26 Javascript
JS中的算法与数据结构之列表(List)实例详解
Aug 16 Javascript
JS highcharts动态柱状图原理及实现
Oct 16 Javascript
一起学写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&amp;&amp;mysql)三
2006/10/09 PHP
is_uploaded_file函数引发的不能上传文件问题
2013/10/29 PHP
codeigniter中view通过循环显示数组数据的方法
2015/03/20 PHP
php 三大特点:封装,继承,多态
2017/02/19 PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
2019/12/04 PHP
Laravel6.18.19如何优雅的切换发件账户
2020/06/14 PHP
JS字符串函数扩展代码
2011/09/13 Javascript
javascript针对DOM的应用分析(二)
2012/04/15 Javascript
onkeydown事件解决按回车键直接提交数据的需求
2013/04/11 Javascript
每天一篇javascript学习小结(Date对象)
2015/11/13 Javascript
JavaScript实现页面跳转的几种常用方式
2015/11/28 Javascript
jquery单击文字或图片内容放大并居中显示
2017/06/23 jQuery
基于Vue实现页面切换左右滑动效果
2020/06/29 Javascript
[js高手之路]从原型链开始图解继承到组合继承的产生详解
2017/08/28 Javascript
vue iview实现动态路由和权限验证功能
2018/04/17 Javascript
详解nuxt路由鉴权(express模板)
2018/11/21 Javascript
JS使用数组实现的队列功能示例
2019/03/04 Javascript
微信JS-SDK实现微信会员卡功能(给用户微信卡包里发送会员卡)
2019/07/25 Javascript
vue实现简单计算商品价格
2020/09/14 Javascript
python3+PyQt5实现使用剪贴板做复制与粘帖示例
2017/01/24 Python
用Python登录好友QQ空间点赞的示例代码
2017/11/04 Python
Python简单生成随机姓名的方法示例
2017/12/27 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
Keras—embedding嵌入层的用法详解
2020/06/10 Python
Python爬虫之Selenium中frame/iframe表单嵌套页面
2020/12/04 Python
作为网站管理者应当如何防范XSS
2014/08/16 面试题
财务会计毕业生个人求职信
2014/02/03 职场文书
行政助理工作职责范本
2014/03/04 职场文书
小学学校评估方案
2014/06/08 职场文书
教师群众路线教育实践活动个人对照检查材料
2014/11/04 职场文书
2014大学班主任工作总结
2014/11/08 职场文书
圆明园观后感
2015/06/03 职场文书
python 模拟在天空中放风筝的示例代码
2021/04/21 Python
Nginx如何配置Http、Https、WS、WSS的方法步骤
2021/05/11 Servers
Js类的构建与继承案例详解
2021/09/15 Javascript
MySQL基础快速入门知识总结(附思维导图)
2021/09/25 MySQL