javascript实现简单的on事件绑定


Posted in Javascript onAugust 23, 2016

实现一个简单的on和off方法

介绍:

Event对象:

   funcList: {}, //保存delegate所绑定的方法  
   ieFuncList :{} //保存ie下的绑定方法

Event 对象中的 on, off 方法,主要调用
Event.addEvent, Event.delegateHandle这两个方法

   Event.addEvent: 调用底层的addEventListener添加监听事件
   Event.delegateHandle: 当发生事件之后,随着事件的冒泡上升,判断存在事件委托的元素,并执行对应的回调函数

addEvent / offEvent:

    obj.addEventListener(type, fn, false);
    obj.removeEventListener(type, fn, false);

代码-Event.js

/**
 * addEvent
 * author laynezhou@tencent.com
 */
window.Event = {};
var Event = {

  funcList: {}, //保存delegate所绑定的方法  
  ieFuncList: {}, //由于保存在ie下绑定的方法


  on: function(obj, selector, type, fn) {
    if (!obj || !selector) return false;
    var fnNew = Event.delegateHandle(obj, selector, fn);
    Event.addEvent(obj, type, fnNew);
    /* 将绑定的方法存入Event.funcList,以便之后解绑操作 */
    if (!Event.funcList[selector]) {
      Event.funcList[selector] = {};
    }
    if (!Event.funcList[selector][type]) {
      Event.funcList[selector][type] = {};
    }

    Event.funcList[selector][type][fn] = fnNew;
  },

  off: function(obj, selector, type, fn) {
    if (!obj || !selector || !Event.funcList[selector]) {
      return false;
    }
    var fnNew = Event.funcList[selector][type][fn];
    if (!fnNew) {
      return;
    }

    Event.offEvent(obj, type, fnNew);
    Event.funcList[selector][type][fn] = null;
  },

  delegateHandle: function(obj, selector, fn) {
    /* 实现delegate 的转换方法,事件冒泡上升时, 符合条件时才会执行回调函数 */
    var func = function(event) {
      var event = event || window.event;
      var target = event.srcElement || event.target;
      var parent = target;

      function contain(item, elmName) {
        if (elmName.split('#')[1]) { //by id
          if (item.id && item.id === elmName.split('#')[1]) {
            return true;
          }
        }
        if (elmName.split('.')[1]) { //by class
          if (hasClass(item, elmName.split('.')[1])) {
            return true;
          }
        }
        if (item.tagName == elmName.toUpperCase()) {
          return true; //by tagname
        }
        return false;
      }
      while (parent) {
        /* 如果触发的元素,属于(selector)元素的子级。 */
        if (obj == parent) {
          return false; //触发元素是自己
        }
        if (contain(parent, selector)) {

          fn.call(obj, event);
          return;
        }
        parent = parent.parentNode;
      }
    };
    return func;
  },
  addEvent: function(target, type, fn) {
    if (!target) return false;
    var add = function(obj) {
      if (obj.addEventListener) {

        obj.addEventListener(type, fn, false);

      } else {
        // for ie
        if (!Event.ieFuncList[obj]) Event.ieFuncList[obj] = {};
        if (!Event.ieFuncList[obj][type]) Event.ieFuncList[obj][type] = {};
        Event.ieFuncList[obj][type][fn] = function() {
          fn.apply(obj, arguments);
        };
        obj.attachEvent("on" + type, Event.ieFuncList[obj][type][fn]);
      }
    }
    if (target.length >= 0 && target !== window && !target.tagName) {
      for (var i = 0, l = target.length; i < l; i++) {
        add(target[i])
      }
    } else {
      add(target);
    }
  },


  offEvent: function(target, type, fn) {
    if (!target) return false;
    var remove = function(obj) {
      if (obj.addEventListener) {
        obj.removeEventListener(type, fn, false);

      } else {
        //for ie
        if (!Event.ieFuncList[obj] || !Event.ieFuncList[obj][type] || !Event.ieFuncList[obj][type][fn]) {
          return;
        }
        obj.detachEvent("on" + type, Event.ieFuncList[obj][type][fn], false);
        Event.ieFuncList[obj][type][fn] = {};
      }
    }
    if (target.length >= 0 && target !== window && !target.tagName) {
      for (var i = 0, l = target.length; i < l; i++) {
        remove(target[i])
      }
    } else {
      remove(target);
    }
  },

};

代码-DEMO.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<p>测试 Event </p>
<div id=content>
  <ul>
    <li><button id="btn1">1</button></li>
    <li><button id="btn2">2</button></li>
    <li><button id="btn3">3</button></li>
    <li><button id="btn4">4</button></li>
    <li><button id="btn5">5</button></li>
  </ul>

<button id="unbind">取消绑定</button>
</div>
<p id="text"></p>

<script src="addEvent.js"></script>
<script>
(function(){
  /* 演示demo*/
  var $id=function(id)
  {
    return document.getElementById(id) || id;
  }
  var outer = $id("content"),
    btn = $id("text");
  Event.on(outer,'button',"click",add);
  Event.on(outer,'#unbind',"click",remove);

  //动态添加一个按钮,查看是否有事件响应
  var newbtn = document.createElement("button");
  var node = document.createTextNode("new button");
  newbtn.appendChild(node);
  outer.appendChild(newbtn);

  function add(){
    var e = arguments[0] || window.event;
    var target = e.srcElement || e.target;
    console.log("target:",target);
    btn.innerHTML = target.innerHTML + ' ' + e.type;
  }
  function remove(){
    Event.off(outer,'button',"click",add);
    Event.off(outer,'#unbind',"click",remove);
  }
})();
</script>
</body>
</html>
Javascript 相关文章推荐
jquery 图片截取工具jquery.imagecropper.js
Apr 09 Javascript
高性能JavaScript循环语句和条件语句
Jan 20 Javascript
Jquery实现的简单轮播效果【附实例】
Apr 19 Javascript
jQuery实现的自动加载页面功能示例
Sep 04 Javascript
Bootstrap基本模板的使用和理解1
Dec 14 Javascript
原生js实现日期计算器功能
Feb 17 Javascript
浅析bootstrap原理及优缺点
Mar 19 Javascript
JS解决position:sticky的兼容性问题的方法
Oct 17 Javascript
vue里面v-bind和Props 利用props绑定动态数据的方法
Aug 27 Javascript
vue axios基于常见业务场景的二次封装的实现
Sep 21 Javascript
vue中使用element组件时事件想要传递其他参数的问题
Sep 18 Javascript
Openlayers+EasyUI Tree动态实现图层控制
Sep 28 Javascript
js实现图片淡入淡出切换简易效果
Aug 22 #Javascript
JS对HTML表格进行增删改操作
Aug 22 #Javascript
AngularJS中$http服务常用的应用及参数
Aug 22 #Javascript
详解AngularJS如何实现跨域请求
Aug 22 #Javascript
深入浅析JS Function()构造函数
Aug 22 #Javascript
深入浅析jQuery对象$.html
Aug 22 #Javascript
基于JavaScript实现添加到购物车效果附源码下载
Aug 22 #Javascript
You might like
搜索和替换文件或目录的一个好类--很实用
2006/10/09 PHP
PHP函数getenv简介和使用实例
2014/05/12 PHP
一些相见恨晚的 JavaScript 技巧
2010/04/25 Javascript
SharePoint 客户端对象模型 (一) ECMA Script
2011/05/22 Javascript
jquery重新播放css动画所遇问题解决
2013/08/21 Javascript
Javascript 按位左移运算符使用介绍(
2014/02/04 Javascript
Jquery对象和Dom对象的区别分析
2014/11/20 Javascript
javascript实现动态改变层大小的方法
2015/05/14 Javascript
在for循环中length值是否需要缓存
2015/07/27 Javascript
Bootstrap入门书籍之(五)导航条、分页导航
2016/02/17 Javascript
关于vuex的学习实践笔记
2017/04/05 Javascript
用vue快速开发app的脚手架工具
2018/06/11 Javascript
vue使用rem实现 移动端屏幕适配
2018/09/26 Javascript
解决Layui数据表格显示无数据提示的问题
2019/11/14 Javascript
vue-quill-editor 自定义工具栏和自定义图片上传路径操作
2020/08/03 Javascript
[46:40]VGJ.T vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
[01:06:43]完美世界DOTA2联赛PWL S3 PXG vs GXR 第二场 12.19
2020/12/24 DOTA
用python代码做configure文件
2014/07/20 Python
使用Python对Access读写操作
2017/03/30 Python
Python实现的字典值比较功能示例
2018/01/08 Python
解决python爬虫中有中文的url问题
2018/05/11 Python
一篇文章搞懂Python的类与对象名称空间
2018/12/10 Python
对Python的zip函数妙用,旋转矩阵详解
2018/12/13 Python
Django 源码WSGI剖析过程详解
2019/08/05 Python
如何将anaconda安装配置的mmdetection环境离线拷贝到另一台电脑
2020/10/15 Python
浅谈基于HTML5的在线视频播放方案
2016/02/18 HTML / CSS
LivingSocial爱尔兰:爱尔兰本地优惠
2018/08/10 全球购物
系统管理员的职责包括那些?管理的对象是什么?
2016/09/20 面试题
宿舍卫生检讨书
2014/01/16 职场文书
金融专业求职信
2014/08/05 职场文书
钳工实训报告总结
2014/11/04 职场文书
2014年高中班主任工作总结
2014/11/08 职场文书
《草船借箭》教学反思
2016/02/23 职场文书
导游词之四川熊猫基地
2020/01/13 职场文书
Pytorch 如何加速Dataloader提升数据读取速度
2021/05/28 Python
MySQL高速缓存启动方法及参数详解(query_cache_size)
2021/07/01 MySQL