详解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获取IUSR_机器名和IWAM_机器名帐号的密码
Dec 06 Javascript
浅析Node在构建超媒体API中的作用
Jul 30 Javascript
JavaScript数据绑定实现一个简单的 MVVM 库
Apr 08 Javascript
原生js实现焦点轮播图效果
Jan 12 Javascript
jQuery Pagination分页插件_动力节点Java学院整理
Jul 17 jQuery
JavaScript 值类型和引用类型的初次研究(推荐)
Jul 19 Javascript
在React中如何优雅的处理事件响应详解
Jul 24 Javascript
用vue构建多页面应用的示例代码
Sep 20 Javascript
vue2 mint-ui loadmore实现下拉刷新,上拉更多功能
Mar 21 Javascript
es6 symbol的实现方法示例
Apr 02 Javascript
vue 使用axios 数据请求第三方插件的使用教程详解
Jul 05 Javascript
node.JS的crypto加密模块使用方法详解(MD5,AES,Hmac,Diffie-Hellman加密)
Feb 06 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指定长度分割字符串str_split函数用法示例
2017/01/30 PHP
Windows平台实现PHP连接SQL Server2008的方法
2017/07/26 PHP
PHPExcel实现的读取多工作表操作示例
2020/04/14 PHP
js函数中onmousedown和onclick的区别和联系探讨
2013/05/19 Javascript
Js 去掉字符串中的空格(实现代码)
2013/11/19 Javascript
Javascript setInterval的两种调用方法(实例讲解)
2013/11/29 Javascript
js中判断用户输入的值是否为空的简单实例
2013/12/23 Javascript
调试代码导致IE出错的避免方法
2014/04/04 Javascript
超赞的动手创建JavaScript框架的详细教程
2015/06/30 Javascript
jQuery EasyUI Pagination实现分页的常用方法
2016/05/21 Javascript
JS函数arguments数组获得实际传参数个数的实现方法
2016/05/28 Javascript
Bootstrap Validator 表单验证
2016/07/25 Javascript
使用React实现轮播效果组件示例代码
2016/09/05 Javascript
JavaScript实现简单的日历效果
2016/09/25 Javascript
ajax级联菜单实现方法实例分析
2016/11/28 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
Vuejs在v-for中,利用index来对第一项添加class的方法
2018/03/03 Javascript
js中split()方法得到的数组长度问题
2018/07/19 Javascript
JS无限级导航菜单实现方法
2019/01/05 Javascript
js实现自动播放匀速轮播图
2020/02/06 Javascript
python实现的希尔排序算法实例
2015/07/01 Python
你眼中的Python大牛 应该都有这份书单
2017/10/31 Python
django admin添加数据自动记录user到表中的实现方法
2018/01/05 Python
python实现人机猜拳小游戏
2020/02/03 Python
django实现模型字段动态choice的操作
2020/04/01 Python
基于canvas使用贝塞尔曲线平滑拟合折线段的方法
2018/01/10 HTML / CSS
为智能设备设计个性化保护套网站:caseable
2017/01/05 全球购物
网友共享的几个面试题关于Java和Unix等方面的
2016/09/08 面试题
优秀食品类广告词
2014/03/19 职场文书
廉洁教育学习材料
2014/05/19 职场文书
公司口号大全
2014/06/11 职场文书
基层干部群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
2015年财务部工作总结
2015/04/10 职场文书
2015年度考核个人工作总结
2015/10/24 职场文书
【2·13】一图读懂中国无线电发展
2022/02/18 无线电
pycharm无法安装cv2模块问题
2022/05/20 Python