详解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 相关文章推荐
javascript add event remove event
Apr 07 Javascript
妙用Jquery的val()方法
Jun 27 Javascript
JavaScript实现自己的DOM选择器原理及代码
Mar 04 Javascript
jquery实现点击展开列表同时隐藏其他列表
Aug 10 Javascript
JavaScript模拟鼠标右键菜单效果
Dec 08 Javascript
移动端 一个简单易懂的弹出框
Jul 06 Javascript
JavaScript数据类型转换的注意事项
Jul 31 Javascript
wap手机端解决返回上一页的js实例
Dec 08 Javascript
js实现图片左右滚动效果
Feb 27 Javascript
jQuery实现多张图片上传预览(不经过后端处理)
Apr 29 jQuery
利用node.js如何搭建一个简易的即时响应服务器
May 28 Javascript
使用vue-cli创建项目的图文教程(新手入门篇)
May 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
destoon官方标签大全
2014/06/20 PHP
CentOS 6.3下安装PHP xcache扩展模块笔记
2014/09/10 PHP
使用ThinkPHP的自动完成实现无限级分类实例详解
2016/09/02 PHP
PHP使用标准库spl实现的观察者模式示例
2018/08/04 PHP
JavaScript iframe的相互操作浅析
2009/10/14 Javascript
jquery使用jquery.zclip插件复制对象的实例教程
2013/12/04 Javascript
js中的时间转换—毫秒转换成日期时间的示例代码
2014/01/26 Javascript
原生js的弹出层且其内的窗口居中
2014/05/14 Javascript
浅谈jQuery中 wrap() wrapAll() 与 wrapInner()的差异
2014/11/12 Javascript
了解Javascript的模块化开发
2015/03/02 Javascript
jquery滚动特效集锦
2015/06/03 Javascript
全系IE支持Bootstrap的解决方法
2015/10/19 Javascript
jQuery实现单击按钮遮罩弹出对话框效果(2)
2017/02/20 Javascript
jQuery的$.extend 浅拷贝与深拷贝
2017/03/08 Javascript
json的结构与遍历方法实例分析
2017/04/25 Javascript
vue.js 实现评价五角星组件的实例代码
2018/08/13 Javascript
javascript实现手动点赞效果
2019/04/09 Javascript
原生js中运算符及流程控制示例详解
2021/01/05 Javascript
Python装饰器使用示例及实际应用例子
2015/03/06 Python
Python pass详细介绍及实例代码
2016/11/24 Python
TensorFlow 实战之实现卷积神经网络的实例讲解
2018/02/26 Python
用HTML5.0制作网页的教程
2010/05/30 HTML / CSS
微软英国官方网站:Microsoft英国
2016/10/15 全球购物
香港礼品网站:GiftU eshop
2017/09/01 全球购物
优秀教师先进事迹
2014/01/22 职场文书
会议室标语
2014/06/21 职场文书
书法兴趣小组活动总结
2014/07/07 职场文书
南京市纪委监察局整改方案
2014/09/16 职场文书
杭白菊导游词
2015/02/10 职场文书
培训督导岗位职责
2015/04/10 职场文书
养成教育主题班会
2015/08/13 职场文书
启迪人心的励志语录:脾气永远不要大于本事
2020/01/02 职场文书
Python类方法总结讲解
2021/07/26 Python
Linux下使用C语言代码搭建一个简单的HTTP服务器
2022/04/13 Servers
详解CSS3浏览器兼容
2022/12/24 HTML / CSS
css弧边选项卡的项目实践
2023/05/07 HTML / CSS