详解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 相关文章推荐
Opacity.js
Jan 22 Javascript
兼容FF和IE的动态table示例自写
Oct 21 Javascript
JavaScript里实用的原生API汇总
May 14 Javascript
Javascript编写俄罗斯方块思路及实例
Jul 07 Javascript
javascript 动态修改css样式方法汇总(四种方法)
Aug 27 Javascript
js实现网站最上边可关闭的浮动广告条代码
Sep 04 Javascript
微信页面弹出键盘后iframe内容变空白的解决方案
Sep 20 Javascript
微信小程序slider组件使用详解
Jan 31 Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
Aug 03 jQuery
基于vue和react的spa进行按需加载的实现方法
Sep 29 Javascript
小程序实现列表点赞功能
Nov 02 Javascript
详解async/await 异步应用的常用场景
May 13 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数组索引的Key加引号和不加引号的区别
2014/08/19 PHP
PHP中基本HTTP认证技巧分析
2015/03/16 PHP
通过源码解析Laravel的依赖注入
2018/01/22 PHP
php的RSA加密解密算法原理与用法分析
2020/01/23 PHP
$()JS小技巧
2007/07/21 Javascript
firefox插件Firebug的使用教程
2010/01/02 Javascript
JSChart轻量级图形报表工具(内置函数中文参考)
2010/10/11 Javascript
Jquery 例外被抛出且未被接住原因介绍
2013/09/04 Javascript
JS仿Windows开机启动Loading进度条的方法
2015/02/26 Javascript
jQuery实现当前页面标签高亮显示的方法
2015/03/10 Javascript
微信小程序中显示html格式内容的方法
2017/04/25 Javascript
vue2.0安装style/css loader的方法
2018/03/14 Javascript
使用electron将vue-cli项目打包成exe的方法
2018/09/29 Javascript
微信小程序实现联动选择器
2019/02/15 Javascript
ant design中upload组件上传大文件,显示进度条进度的实例
2020/10/29 Javascript
python实现将html表格转换成CSV文件的方法
2015/06/28 Python
详谈在flask中使用jsonify和json.dumps的区别
2018/03/26 Python
python高阶爬虫实战分析
2018/07/29 Python
python画柱状图--不同颜色并显示数值的方法
2018/12/13 Python
Python for i in range ()用法详解
2020/09/18 Python
python使用信号量动态更新配置文件的操作
2020/04/01 Python
浅谈Python中的字符串
2020/06/10 Python
纯CSS3实现圆角效果(含IE兼容解决方法)
2014/05/07 HTML / CSS
飞利浦比利时官方网站:Philips比利时
2016/08/24 全球购物
英国最大的自有市场,比亚马逊便宜:Flubit
2019/03/19 全球购物
yy结婚证婚词
2014/01/10 职场文书
医院检讨书范文
2014/02/01 职场文书
生物制药专业自我鉴定
2014/02/19 职场文书
进口业务员岗位职责
2014/04/06 职场文书
大学生应聘导游自荐信
2014/06/02 职场文书
公司股东合作协议书
2014/09/14 职场文书
“四风”问题整改措施和努力方向
2014/09/20 职场文书
土地转让协议书
2014/09/27 职场文书
检讨书格式
2015/05/07 职场文书
西安事变观后感
2015/06/12 职场文书
Spring整合Mybatis的全过程
2021/06/28 Java/Android