JavaScript动态绑定详解


Posted in Javascript onSeptember 14, 2017

问题描述:

假设我们的网页中动态生成了一个按钮,在这个按钮生成之前我们按照一般的事件绑定方法为此按钮绑定了触发事件,但是问题是绑定的事件并没有生效(JavaScript中为元素绑定的事件失效)

分析

1.首先我们来看一下这个按钮是怎么回事:

问题中按钮有一个很关键的特性:动态生成,也就是说是在网页加载完成之后执行某些操作才产生的,它一开始是不存在的;

2.然后我们来分析一下事件的绑定

对于动态生成的元素,它不同于一般的网页既有元素,它的事件绑定不能通过普通的事件绑定实现。

3.关于JavaScript事件绑定的小解(针对本题盗图解析)

这里写图片描述

由图中我们可以看到事件冒泡即由最具体的元素(文档嵌套最深节点)接收,然后逐步上传至document

事件捕获会由最先接收到事件的元素然后传向最里边(我们可以将元素想象成一个盒子装一个盒子,而不是一个积木堆积)

然后我们进入dom事件流

DOM2级事件规定事件包括三个阶段:

① 事件捕获阶段

② 处于目标阶段

③ 事件冒泡阶段

我们分析一下第一阶段就可以知道为什么了,js中一般事件绑定是在网页生成的时候针对具体元素去绑定的,那么请问:网页初始生成时按钮存在吗?答:NOP。这就是为什么事件没有绑定上去,因为都没找到元素啊啊啊啊啊,绑个毛线

解决方法(jQuery on方法)

通过将事件绑定到存在的父元素上让子元素的事件有效

jQuery on用法格式:

$(selector).on(event,childSelector,data,function,map)

示例,比如说id为btn的元素为动态生成,它的父元素为btnParent(必须是网页加载时就有的元素,也可以直接绑定到body上去)那么我们可以这样为它绑定处理事件

$("#btnParent").on("click","#btn",function(){
  console.log('binded!');
 });

如果想要更深层次的理解,那么请跟我一起阅读一下jQuery.on()的源码实现

on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
  var type, origFn;

  // 类型可以使类型映射或者句柄映射
  if ( typeof types === "object" ) {
    // ( types-Object, selector, data )
    if ( typeof selector !== "string" ) {
      // ( types-Object, data )
      data = data || selector;
      selector = undefined;
    }
    // 遍历types对象,针对每一个属性绑定on()方法
    // 将types[type]作为fn传入
    for ( type in types ) {
      this.on( type, selector, data, types[ type ], one );
    }
    return this;
  }

  // 参数修正
  // jQuery这种参数修正的方法很好
  // 可以兼容多种参数形式
  // 可见在灵活调用的背后做了很多处理
  if ( data == null && fn == null ) {
    // ( types, fn )
    fn = selector;
    data = selector = undefined;
  } else if ( fn == null ) {
    if ( typeof selector === "string" ) {
      // ( types, selector, fn )
      fn = data;
      data = undefined;
    } else {
      // ( types, data, fn )
      fn = data;
      data = selector;
      selector = undefined;
    }
  }
  if ( fn === false ) {
    // fn传入false时,阻止该事件的默认行为
    // function returnFalse() {return false;}
    fn = returnFalse;
  } else if ( !fn ) {
    return this;
  }

  // one()调用on()
  if ( one === 1 ) {
    origFn = fn;
    fn = function( event ) {
      // Can use an empty set, since event contains the info
      // 用一个空jQuery对象,这样可以使用.off方法,
      // 并且event带有remove事件需要的信息
      jQuery().off( event );
      return origFn.apply( this, arguments );
    };
    // Use same guid so caller can remove using origFn
    // 事件删除依赖于guid
    fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  }

  // 这里调用jQuery的each方法遍历调用on()方法的jQuery对象
  // 如$('li').on(...)则遍历每一个li传入add()
  // 推荐使用$(document).on()或者集合元素的父元素
  return this.each( function() {
    jQuery.event.add( this, types, fn, data, selector );
  });
},

关于jQuery还有很多其他的事件绑定方法,当然不一定适用,也提一下

.bind(), .live(), .delegate()

但是说到底.bind(), .live(), .delegate()都是通过.on()来实现的,.unbind(), .die(), .undelegate(),也是一样的都是通过.off()来实现的

我们看一下jQuery的.bind(), .live(), .delegate()的实现源码就清楚了

jQuery.fn.extend( {

  bind: function( types, data, fn ) {
    return this.on( types, null, data, fn );
    //注意this.on()
  },
  unbind: function( types, fn ) {
    return this.off( types, null, fn );
    //注意this.off()
  },

  delegate: function( selector, types, data, fn ) {
    return this.on( types, selector, data, fn );
  },
  undelegate: function( selector, types, fn ) {
    return arguments.length === 1 ?
      this.off( selector, "**" ) :
      this.off( types, selector || "**", fn );
  }
} );

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
(转载)JavaScript中匿名函数,函数直接量和闭包
May 08 Javascript
javascript优先加载笔记代码
Sep 30 Javascript
js onload事件不起作用示例分析
Oct 09 Javascript
各种常用的JS函数整理
Oct 25 Javascript
js中的内部属性与delete操作符介绍
Aug 10 Javascript
JS实现选中当前菜单后高亮显示的导航条效果
Oct 15 Javascript
JS实现的页面自定义滚动条效果
Oct 26 Javascript
JavaScript中的return语句简单介绍
Dec 07 Javascript
javascript使用Promise对象实现异步编程
Mar 01 Javascript
Javascript highcharts 饼图显示数量和百分比实例代码
Dec 06 Javascript
详解Python中logging日志模块在多进程环境下的使用
Dec 26 Javascript
浅谈TypeScript 用 Webpack/ts-node 运行的配置记录
Oct 11 Javascript
React-Native使用Mobx实现购物车功能
Sep 14 #Javascript
JavaScript requestAnimationFrame动画详解
Sep 14 #Javascript
SVG动画vivus.js库使用小结(实例代码)
Sep 14 #Javascript
浅谈AngularJS中使用$resource(已更新)
Sep 14 #Javascript
jQuery plugin animsition使用小结
Sep 14 #jQuery
angular.extend方法的具体使用
Sep 14 #Javascript
浅谈angular.copy() 深拷贝
Sep 14 #Javascript
You might like
php2html php生成静态页函数
2008/12/08 PHP
深入理解:XML与对象的序列化与反序列化
2013/06/08 PHP
PHP 返回13位时间戳的实现代码
2016/05/13 PHP
PHP实现单文件、多个单文件、多文件上传函数的封装示例
2019/09/02 PHP
prototype 1.5 & scriptaculous 1.6.1 学习笔记
2006/09/07 Javascript
理清apply(),call()的区别和关系
2011/08/14 Javascript
javascript对talbe进行动态添加、删除、验证实现代码
2012/03/29 Javascript
javascript通过class来获取元素实现代码
2013/02/20 Javascript
jQuery+Ajax实现无刷新分页
2015/10/30 Javascript
bootstrap网格系统使用方法解析
2017/01/13 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
微信小程序 生命周期函数详解
2017/05/24 Javascript
localstorage实现带过期时间的缓存功能
2019/06/28 Javascript
jQuery提示框插件SweetAlert用法分析
2019/08/05 jQuery
NodeJS 文件夹拷贝以及删除功能
2019/09/03 NodeJs
Vue 使用typescript如何优雅的调用swagger API
2020/09/01 Javascript
[01:20]DOTA2 齐天大圣至宝动态展示
2016/12/13 DOTA
Python求出0~100以内的所有素数
2018/01/23 Python
基于Python pip用国内镜像下载的方法
2018/06/12 Python
python中嵌套函数的实操步骤
2019/02/27 Python
python getpass模块用法及实例详解
2019/10/07 Python
Python中的With语句的使用及原理
2020/07/29 Python
如何利用Python 进行边缘检测
2020/10/14 Python
HTML5超文本标记语言的实现方法
2020/09/24 HTML / CSS
预订奥兰多和佛罗里达州公园门票:FloridaTix
2018/01/03 全球购物
匡威意大利官方商店 :Converse意大利
2018/11/27 全球购物
Otticanet意大利:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
毕业自我鉴定
2013/11/05 职场文书
求职简历推荐信范文
2013/12/02 职场文书
学习雷锋标语
2014/06/25 职场文书
党员对照检查材料整改措施思想汇报
2014/09/26 职场文书
2014年财务工作总结与计划
2014/12/08 职场文书
银行优秀员工推荐信
2015/03/24 职场文书
2015年学校综合治理工作总结
2015/07/20 职场文书
Redis如何使用乐观锁(CAS)保证数据一致性
2022/03/25 Redis
国际最新研究在陨石中发现DNA主要成分 或由陨石带来地球
2022/04/29 数码科技