详解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 OOP包机制,类创建的方法定义
Nov 02 Javascript
在模板页面的js使用办法
Apr 01 Javascript
jQuery 表单验证扩展(四)
Oct 20 Javascript
jquery五角星评分插件示例分享
Feb 21 Javascript
javascript遇到html5的一些表单属性
Jul 05 Javascript
JavaScript中全选、全不选、反选、无刷新删除、批量删除、即点即改入库(在yii框架中操作)的代码分享
Nov 01 Javascript
jQuery给表格添加分页效果
Mar 02 Javascript
Vue渲染函数详解
Sep 15 Javascript
vue源码学习之Object.defineProperty 对数组监听
May 30 Javascript
详解如何在Angular优雅编写HTTP请求
Dec 05 Javascript
vue3.0中的双向数据绑定方法及优缺点
Aug 01 Javascript
vue中如何实现后台管理系统的权限控制的方法步骤
Sep 05 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
Terran建筑一览
2020/03/14 星际争霸
PHP中计算字符串相似度的函数代码
2012/12/29 PHP
Linux下创建nginx脚本-start、stop、reload…
2014/08/03 PHP
innerhtml用法 innertext用法 以及innerHTML与innertext的区别
2009/10/26 Javascript
JS控制显示隐藏兼容问题(IE6、IE7、IE8)
2010/04/01 Javascript
javascript基础第一章 JavaScript与用户端
2010/07/22 Javascript
JS上传图片前的限制包括(jpg jpg gif及大小高宽)等
2012/12/19 Javascript
jQuery中:hidden选择器用法实例
2014/12/30 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(下)
2015/10/28 Javascript
Bootstrap学习笔记之js组件(4)
2016/06/12 Javascript
Bootstrap基本组件学习笔记之input输入框组(9)
2016/12/07 Javascript
jQuery展示表格点击变色、全选、删除
2017/01/05 Javascript
jquery append与appendTo方法比较
2017/05/24 jQuery
React教程之Props验证的具体用法(Props Validation)
2017/09/04 Javascript
jQueryUI Sortable 应用Demo(分享)
2017/09/07 jQuery
在Vue中使用icon 字体图标的方法
2019/06/14 Javascript
js HTML DOM EventListener功能与用法实例分析
2020/04/27 Javascript
[02:17]2016完美“圣”典风云人物:Sccc专访
2016/12/03 DOTA
Python中urllib2模块的8个使用细节分享
2015/01/01 Python
Python使用cx_Oracle模块将oracle中数据导出到csv文件的方法
2015/05/16 Python
django.db.utils.ProgrammingError: (1146, u“Table‘’ doesn’t exist”)问题的解决
2018/07/13 Python
python 递归深度优先搜索与广度优先搜索算法模拟实现
2018/10/22 Python
Python小程序之在图片上加入数字的代码
2019/11/26 Python
Python中Flask-RESTful编写API接口(小白入门)
2019/12/11 Python
基于python读取.mat文件并取出信息
2019/12/16 Python
jupyter 实现notebook中显示完整的行和列
2020/04/09 Python
GAP欧盟网上商店:GAP EU
2016/09/13 全球购物
Probikekit日本:自行车套件,跑步和铁人三项装备
2017/04/03 全球购物
外企办公室竞聘演讲稿
2013/12/29 职场文书
酒店销售经理岗位职责
2014/01/31 职场文书
物业管理工作方案
2014/05/10 职场文书
春游踏青活动方案
2014/08/14 职场文书
护士长2014年度工作总结
2014/11/11 职场文书
现役军人家属慰问信
2015/03/24 职场文书
OpenStack虚拟机快照和增量备份实现方法
2022/04/04 Servers
六个好看实用的 HTML + CSS 后台登录入口页面
2022/04/28 HTML / CSS