详解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实现页面自适应
Jan 19 Javascript
基于jquery的回到页面顶部按钮
Jun 27 Javascript
js实现缓冲运动效果的方法
Apr 10 Javascript
基于javascript实现图片懒加载
Jan 05 Javascript
Google 地图API资料整理及详细介绍
Aug 06 Javascript
js带闹铃功能的倒计时代码
Sep 29 Javascript
JS库之Three.js 简易入门教程(详解之一)
Sep 13 Javascript
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
Jan 08 jQuery
200行代码实现blockchain 区块链实例详解
Mar 14 Javascript
element-ui使用导航栏跳转路由的用法详解
Aug 22 Javascript
vue项目引入Iconfont图标库的教程图解
Oct 24 Javascript
基于Ionic3实现选项卡切换并重新加载echarts
Sep 24 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 EOT定界符的使用详解
2008/09/30 PHP
ASP.NET中使用后端代码注册脚本 生成JQUERY-EASYUI的界面错位的解决方法
2010/06/12 Javascript
Javascript实现CheckBox的全选与取消全选的代码
2010/07/20 Javascript
深入理解JavaScript系列(4) 立即调用的函数表达式
2012/01/15 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
了解一点js的Eval函数
2012/07/26 Javascript
js中的数组Array定义与sort方法使用示例
2013/08/29 Javascript
JavaScript面向对象编程入门教程
2014/04/16 Javascript
在Google 地图上实现做的标记相连接
2015/01/05 Javascript
window.onload与$(document).ready()的区别分析
2015/05/30 Javascript
浏览器兼容性问题大汇总
2015/12/17 Javascript
jQuery与JS加载事件用法分析
2016/09/04 Javascript
小程序实现左滑删除功能
2018/10/30 Javascript
在layui下对元素进行事件绑定的实例
2019/09/06 Javascript
Nodejs文件上传、监听上传进度的代码
2020/03/27 NodeJs
pycharm 使用心得(三)Hello world!
2014/06/05 Python
web.py在SAE中的Session问题解决方法(使用mysql存储)
2015/06/24 Python
一些常用的Python爬虫技巧汇总
2016/09/28 Python
python3 模拟登录v2ex实例讲解
2017/07/13 Python
Python实现将Excel转换成xml的方法示例
2018/08/25 Python
浅谈python的深浅拷贝以及fromkeys的用法
2019/03/08 Python
详解Python:面向对象编程
2019/04/10 Python
python将时分秒转换成秒的实例
2019/12/07 Python
Python3 A*寻路算法实现方式
2019/12/24 Python
Python实现aes加密解密多种方法解析
2020/05/15 Python
完美解决TensorFlow和Keras大数据量内存溢出的问题
2020/07/03 Python
Python创建文件夹与文件的快捷方法
2020/12/08 Python
大女孩胸罩:Big Girls Bras
2016/12/15 全球购物
自我鉴定模板
2013/10/29 职场文书
公司培训心得体会
2014/01/03 职场文书
初中科学教学反思
2014/01/21 职场文书
学生吸烟检讨书
2014/09/14 职场文书
2014年接待工作总结
2014/11/26 职场文书
财务会计岗位职责
2015/02/03 职场文书
SQL SERVER中常用日期函数的具体使用
2021/04/08 SQL Server
PostgreSQL并行计算算法及参数强制并行度设置方法
2022/04/06 PostgreSQL