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 相关文章推荐
JavaScript窗口功能指南之在窗口中书写内容
Jul 21 Javascript
javascript 检测浏览器类型和版本的代码
Sep 15 Javascript
eval与window.eval的差别分析
Mar 17 Javascript
Extjs4 类的定义和扩展实例
Jun 28 Javascript
Chrome下ifame父窗口调用子窗口的问题示例探讨
Mar 17 Javascript
$.each遍历对象、数组的属性值并进行处理
Jul 18 Javascript
JS实现动态增加和删除li标签行的实例代码
Oct 16 Javascript
Bootstrap模态框插件使用详解
May 11 Javascript
Angularjs中数据绑定的实例详解
Aug 25 Javascript
vue中$refs的用法及作用详解
Apr 24 Javascript
微信小程序3D轮播实现代码
Sep 19 Javascript
原生JS实现多条件筛选
Aug 19 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
PHP下对字符串的递增运算代码
2010/08/21 PHP
php unset全局变量运用问题的深入解析
2013/06/17 PHP
PHP针对JSON操作实例分析
2015/01/12 PHP
PHP判断当前使用的是什么浏览器(推荐)
2019/10/27 PHP
javascript 强制刷新页面的实现代码
2009/12/13 Javascript
下载网站打开页面后间隔多少时间才显示下载链接地址的代码
2010/04/25 Javascript
JavaScript Ajax Json实现上下级下拉框联动效果实例代码
2013/11/23 Javascript
jQuery 获取、设置HTML或TEXT内容的两种方法
2014/05/23 Javascript
浅谈Javascript实现继承的方法
2015/07/06 Javascript
jQuery ajax时间差导致的变量赋值问题分析
2016/01/22 Javascript
node.js 中国天气预报 简单实现
2016/06/06 Javascript
第一次动手实现bootstrap table分页效果
2016/09/22 Javascript
form+iframe解决跨域上传文件的方法
2016/11/18 Javascript
原生JS下拉加载插件分享
2016/12/26 Javascript
Angularjs使用ng-repeat中$even和$odd属性的注意事项
2016/12/31 Javascript
基于vue的fullpage.js单页滚动插件
2017/03/20 Javascript
jQuery插件FusionCharts绘制的3D双柱状图效果示例【附demo源码】
2017/04/20 jQuery
zTree树形插件异步加载方法详解
2017/06/14 Javascript
vue数字类型过滤器的示例代码
2017/09/07 Javascript
Vue.js实现图片的随意拖动方法
2018/03/08 Javascript
详解vue-flickity的fullScreen功能实现
2020/04/07 Javascript
Vue组件跨层级获取组件操作
2020/07/27 Javascript
vue实现移动端返回顶部
2020/10/12 Javascript
python实现中文转换url编码的方法
2016/06/14 Python
python dataframe 输出结果整行显示的方法
2018/06/14 Python
python面试题之列表声明实例分析
2019/07/08 Python
windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码
2020/05/07 Python
浅析rem和em和px vh vw和% 移动端长度单位
2016/04/28 HTML / CSS
MVMT手表官方网站:时尚又实惠的高品质手表
2016/12/04 全球购物
自1926年以来就为冰岛保持温暖:66°North
2020/11/27 全球购物
财政局党的群众路线教育实践活动整改方案
2014/09/21 职场文书
2015年酒店工作总结范文
2015/04/07 职场文书
幼儿园教师心得体会范文
2016/01/21 职场文书
如何写好闭幕词
2019/04/02 职场文书
导游词书写之黄山
2019/08/06 职场文书
关于maven依赖 ${xxx.version}报错问题
2022/01/18 Java/Android