详解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 相关文章推荐
动感效果的TAB选项卡jquery 插件
Jul 09 Javascript
javascript中RegExp保留小数点后几位数的方法分享
Aug 13 Javascript
JS图片无缝、平滑滚动代码
Mar 11 Javascript
js限制文本框只能输入数字方法小结
Jun 16 Javascript
简单易用的倒计时js代码
Aug 04 Javascript
详解JavaScript ES6中的模板字符串
Jul 28 Javascript
jQuery+css3实现文字跟随鼠标的上下抖动
Jul 31 Javascript
jQuery checkbox选中问题之prop与attr注意点分析
Nov 15 Javascript
jQuery实现手机上输入后隐藏键盘功能
Jan 04 Javascript
JS实现动态给标签控件添加事件的方法示例
May 13 Javascript
浅析Vue项目中使用keep-Alive步骤
Jul 27 Javascript
原生js实现公告滚动效果
Jan 10 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批量生成缩略图的代码
2008/07/19 PHP
PHP日志LOG类定义与用法示例
2018/09/06 PHP
基于Jquery的动态创建DOM元素的代码
2010/12/28 Javascript
js判断浏览器是否支持严格模式的方法
2016/10/04 Javascript
js 获取今天以及过去日期
2017/04/11 Javascript
JS使用插件cryptojs进行加密解密数据实例
2017/05/11 Javascript
AngularJS中table表格基本操作示例
2017/10/10 Javascript
原生js实现简单的焦点图效果实例
2017/12/14 Javascript
从零开始最小实现react服务器渲染详解
2018/01/26 Javascript
微信小程序自定义音乐进度条的实例代码
2018/08/28 Javascript
原生js实现商品筛选功能
2019/10/28 Javascript
js实现坦克大战游戏
2020/02/24 Javascript
详解vue路由
2020/08/05 Javascript
在Vue中获取自定义属性方法:data-id的实例
2020/09/09 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
Python图片裁剪实例代码(如头像裁剪)
2017/06/21 Python
python3获取当前文件的上一级目录实例
2018/04/26 Python
Python中property函数用法实例分析
2018/06/04 Python
在cmd中查看python的安装路径方法
2019/07/03 Python
Python之——生成动态路由轨迹图的实例
2019/11/22 Python
python实现监控阿里云账户余额功能
2019/12/16 Python
用python绘制樱花树
2020/10/09 Python
pycharm 2020.2.4 pip install Flask 报错 Error:Non-zero exit code的问题
2020/12/04 Python
巧用CSS3 border实现图片遮罩效果代码
2012/04/09 HTML / CSS
韩语专业本科生求职信
2013/10/01 职场文书
工作自我评价怎么写
2014/01/29 职场文书
银行竞聘演讲稿
2014/05/16 职场文书
消防安全宣传口号
2014/06/10 职场文书
个人债务授权委托书
2014/10/17 职场文书
2016猴年开门红标语口号
2015/12/26 职场文书
pytorch训练神经网络爆内存的解决方案
2021/05/22 Python
Django实现drf搜索过滤和排序过滤
2021/06/21 Python
elasticSearch-api的具体操作步骤讲解
2021/06/28 Java/Android
【海涛教你打dota】体验一超神发条:咱是抢盾专业户
2022/04/01 DOTA
Python自动化工具之实现Excel转Markdown表格
2022/04/08 Python
Golang实现可重入锁的示例代码
2022/05/25 Golang