详解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 相关文章推荐
jQuery 动画基础教程
Dec 25 Javascript
日历查询的算法 如何计算某一天是星期几
Dec 12 Javascript
基于jQuery实现网页进度显示插件
Mar 04 Javascript
JavaScript中的闭包介绍
Mar 15 Javascript
深入分析Javascript跨域问题
Apr 17 Javascript
js实现对ajax请求面向对象的封装
Jan 08 Javascript
三种Node.js写文件的方式
Mar 08 Javascript
微信小程序 在线支付功能的实现
Mar 14 Javascript
分分钟学会vue中vuex的应用(入门教程)
Sep 14 Javascript
React中使用UEditor百度富文本的方法
Aug 22 Javascript
js实现简易ATM功能
Oct 27 Javascript
利用vue3+ts实现管理后台(增删改查)
Oct 30 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格式化显示时间date()函数代码
2018/10/03 PHP
struts2 jquery 打造无限层次的树
2009/10/23 Javascript
基于jQuery架构javascript基础体系
2011/01/01 Javascript
JavaScript中将一个值转换为字符串的方法分析[译]
2012/09/21 Javascript
JQuery的read函数与js的onload不同方式实现
2013/03/18 Javascript
javascript表单验证和Window详解
2014/12/11 Javascript
JavaScript调用客户端Java程序的方法
2015/07/27 Javascript
JQuery Mobile实现导航栏和页脚
2016/03/09 Javascript
confirm确认对话框的实现方法总结
2016/06/17 Javascript
浅谈Javascript中的12种DOM节点类型
2016/08/19 Javascript
AngularJS入门教程之表单校验用法示例
2016/11/02 Javascript
利用jquery实现实时更新歌词的方法
2017/01/06 Javascript
详解利用jsx写vue组件的方法示例
2017/07/17 Javascript
nodejs动态创建二维码的方法
2017/08/12 NodeJs
jquery应用实例分享_实现手风琴特效
2018/02/01 jQuery
vue加载自定义的js文件方法
2018/03/13 Javascript
Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)
2018/08/24 Javascript
jquery插件开发模式实例详解
2019/07/20 jQuery
解决vue单页面 回退页面 keeplive 缓存问题
2020/07/22 Javascript
基于JavaScript实现大文件上传后端代码实例
2020/08/18 Javascript
Python实现股市信息下载的方法
2015/06/15 Python
Python中的模块导入和读取键盘输入的方法
2015/10/16 Python
python查看微信好友是否删除自己
2016/12/19 Python
python实现百万答题自动百度搜索答案
2018/01/16 Python
pygame实现俄罗斯方块游戏
2018/06/26 Python
使用 Python 快速实现 HTTP 和 FTP 服务器的方法
2019/07/22 Python
详解python 内存优化
2020/08/17 Python
手机端用rem+scss做适配的详解
2017/11/15 HTML / CSS
奥地利顶级内衣丝袜品牌英国站:Wolford英国
2016/08/29 全球购物
JAVA招聘远程笔试题
2015/07/23 面试题
机械专业毕业生自荐信
2013/11/02 职场文书
高中生期末评语
2014/01/28 职场文书
求职简历的自我评价
2014/01/31 职场文书
护士毕业自我鉴定
2014/02/07 职场文书
观看焦裕禄观后感
2015/06/09 职场文书
告诉你一个秘密:富人致富的五大优点
2019/07/11 职场文书