详解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实现的页内搜索代码
May 23 Javascript
jquery实现图片滚动效果的简单实例
Nov 23 Javascript
jquery实现动态菜单的实例代码
Nov 28 Javascript
js select option对象小结
Dec 20 Javascript
js确认删除对话框效果的示例代码
Feb 20 Javascript
鼠标悬浮显示二级菜单效果的jquery实现
Oct 29 Javascript
Javascript实现网络监测的方法
Jul 31 Javascript
JS获取input file绝对路径的方法(推荐)
Aug 02 Javascript
JavaScript 中 avalon绑定属性总结
Oct 19 Javascript
Vue3 中的数据侦测的实现
Oct 09 Javascript
JavaScript冒泡算法原理与实现方法深入理解
Jun 04 Javascript
微信小程序实现转盘抽奖
Sep 21 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设计模式 Chain Of Responsibility (职责链模式)
2011/06/26 PHP
php中判断字符串是否全是中文或含有中文的实现代码
2011/09/16 PHP
php中jpgraph类库的使用介绍
2013/08/08 PHP
jQuery 学习第六课 实现一个Ajax的TreeView
2010/05/17 Javascript
基于JQuery的类似新浪微博展示信息效果的代码
2012/07/23 Javascript
Js数组的操作push,pop,shift,unshift等方法详细介绍
2012/12/28 Javascript
jQuery.buildFragment使用方法及思路分析
2013/01/07 Javascript
Extjs4 类的定义和扩展实例
2013/06/28 Javascript
jquery1.10给新增元素绑定事件的方法
2014/03/06 Javascript
jquery 按键盘上的enter事件
2014/05/11 Javascript
javascript里绝对用的上的字符分割函数总结
2014/07/31 Javascript
jquery操作angularjs对象
2015/06/26 Javascript
js游戏人物上下左右跑步效果代码分享
2015/08/28 Javascript
vue.js实例对象+组件树的详细介绍
2017/10/20 Javascript
分享vue.js devtools遇到一系列问题
2017/10/24 Javascript
微信小程序动态生成二维码的实现代码
2018/07/25 Javascript
JS实现水平遍历和嵌套递归操作示例
2019/08/15 Javascript
layer.open 子页面弹出层向父页面传输数据的例子
2019/09/26 Javascript
[02:20]DOTA2中文配音宣传片
2013/05/22 DOTA
[01:04:02]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第二场 1月24日
2021/03/11 DOTA
python数据结构之二叉树的遍历实例
2014/04/29 Python
详解python的webrtc库实现语音端点检测
2017/05/31 Python
python通过elixir包操作mysql数据库实例代码
2018/01/31 Python
详解Matplotlib绘图之属性设置
2019/08/23 Python
win7上tensorflow2.2.0安装成功 引用DLL load failed时找不到指定模块 tensorflow has no attribute xxx 解决方法
2020/05/20 Python
python 基于opencv 实现一个鼠标绘图小程序
2020/12/11 Python
世界最大的票务市场:viagogo
2017/02/16 全球购物
执行力心得体会
2013/12/31 职场文书
《小儿垂钓》教学反思
2014/02/23 职场文书
社区母亲节活动记录
2014/03/06 职场文书
老人祝寿主持词
2014/03/28 职场文书
培训讲师岗位职责
2014/04/13 职场文书
学术会议通知范文
2015/04/15 职场文书
2016教师节感恩话语
2015/12/09 职场文书
描述鲁迅的名言整理,一生受用
2019/08/08 职场文书
java设计模式--建造者模式详解
2021/07/21 Java/Android