详解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 相关文章推荐
不使用中间变量,交换int型的 a, b两个变量的值。
Oct 29 Javascript
js 输出内容到新窗口具体实现代码
May 31 Javascript
JS 对输入框进行限制(常用的都有)
Jul 30 Javascript
jqGrid随窗口大小变化自适应大小的示例代码
Dec 28 Javascript
AngularJS向后端ASP.NET API控制器上传文件
Feb 03 Javascript
js实现简单的省市县三级联动效果实例
Feb 18 Javascript
基于jQuery实现仿搜狐辩论投票动画代码(附源码下载)
Feb 18 Javascript
JS动态改变浏览器标题的方法
Apr 06 Javascript
javascript循环链表之约瑟夫环的实现方法
Jan 16 Javascript
JS实现新建文件夹功能
Jun 17 Javascript
webpack学习笔记之代码分割和按需加载的实例详解
Jul 20 Javascript
利用vue和element-ui设置表格内容分页的实例
Mar 02 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.MVC的模板标签系统(四)
2006/09/05 PHP
PHP求最大子序列和的算法实现
2011/06/24 PHP
PHP操作MongoDB GridFS 存储文件的详解
2013/06/20 PHP
ThinkPHP中的常用查询语言汇总
2014/08/22 PHP
PHP常用的排序和查找算法
2015/08/06 PHP
php基于curl实现的股票信息查询类实例
2016/11/11 PHP
laravel 解决ajax异步提交数据,并还回填充表格的问题
2019/10/15 PHP
利用百度地图JSAPI生成h7n9禽流感分布图实现代码
2013/04/15 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
jQuery基于当前元素进行下一步的遍历
2014/05/20 Javascript
JavaScript动态修改网页元素内容的方法
2015/03/21 Javascript
JavaScript中使用Math.floor()方法对数字取整
2015/06/15 Javascript
你有必要知道的25个JavaScript面试题
2015/12/29 Javascript
webpack 代码分离优化快速指北
2019/05/18 Javascript
微信小程序实现动态列表项的顺序加载动画
2019/07/25 Javascript
解决vue语法会有延迟加载显现{{xxx}}的问题
2019/11/14 Javascript
js实现磁性吸附的示例
2020/10/26 Javascript
解决Antd Table组件表头不对齐的问题
2020/10/27 Javascript
[01:02:03]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS VG
2014/05/26 DOTA
[01:32]2016国际邀请赛中国区预选赛CDEC战队教练采访
2016/06/26 DOTA
收集的几个Python小技巧分享
2014/11/22 Python
Python实现的RSS阅读器实例
2015/07/25 Python
Python生成随机数组的方法小结
2017/04/15 Python
python通过实例讲解反射机制
2019/10/17 Python
Python+Kepler.gl实现时间轮播地图过程解析
2020/07/20 Python
ORACLE十问
2015/04/20 面试题
.NET面试问题集
2015/12/08 面试题
个人自我评价范文
2014/02/05 职场文书
岗位职责风险防控
2014/02/18 职场文书
护校行动方案
2014/05/31 职场文书
2015年世界环境日活动方案
2015/05/05 职场文书
2015年出纳年终工作总结
2015/05/14 职场文书
班干部学习委员竞选稿
2015/11/20 职场文书
Nginx配置80端口访问8080及项目名地址方法解析
2021/03/31 Servers
python计算列表元素与乘积详情
2022/08/05 Python
详解Golang如何实现支持随机删除元素的堆
2022/09/23 Python