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 相关文章推荐
在IE模态窗口中自由查看HTML源码的方法
Mar 08 Javascript
基于JavaScript自定义构造函数的详解说明
Apr 24 Javascript
当鼠标移动到图片上时跟随鼠标显示放大的图片效果
Jun 06 Javascript
深入理解JavaScript系列(37):设计模式之享元模式详解
Mar 04 Javascript
JavaScript监听文本框回车事件并过滤文本框空格的方法
Apr 16 Javascript
通过XMLHttpRequest和jQuery实现ajax的几种方式
Aug 28 Javascript
jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点
Dec 01 Javascript
基于JavaScript FileReader上传图片显示本地链接
May 27 Javascript
node.js的事件机制
Feb 08 Javascript
微信小程序组件之srcoll-view的详解
Oct 19 Javascript
vue页面跳转后返回原页面初始位置方法
Feb 11 Javascript
Swiper实现导航栏滚动效果
Oct 16 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
CURL的学习和应用(附多线程实现)
2013/06/03 PHP
浅谈使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势
2017/11/08 PHP
PHP实现生成数据字典功能示例
2018/05/24 PHP
laravel5.1框架model类查询的实现方法
2019/10/08 PHP
JS宝典学习笔记(下)
2007/01/10 Javascript
Input 特殊事件onpopertychange和oninput
2009/06/17 Javascript
一个网马的tips实现分析
2010/11/28 Javascript
使用JavaScript构建JSON格式字符串实现步骤
2013/03/22 Javascript
『jQuery』名称冲突使用noConflict方法解决
2013/04/22 Javascript
js图片闪动特效可以控制间隔时间如几分钟闪动一下
2014/08/12 Javascript
js一维数组、多维数组和对象的混合使用方法
2016/04/03 Javascript
Bootstrap表单Form全面解析
2016/06/13 Javascript
利用Angular.js限制textarea输入的字数
2016/10/20 Javascript
Angularjs使用ng-repeat中$even和$odd属性的注意事项
2016/12/31 Javascript
浅谈$_FILES数组为空的原因
2017/02/16 Javascript
ES6中Generator与异步操作实例分析
2017/03/31 Javascript
在Vue中使用Compass的方法
2018/03/02 Javascript
element-ui中的select下拉列表设置默认值方法
2018/08/24 Javascript
微信小程序缓存过期时间的使用详情
2019/05/12 Javascript
NodeJs实现简易WEB上传下载服务器
2019/08/10 NodeJs
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
[37:45]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS Orenda
2014/05/22 DOTA
[56:01]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 Effect vs EG
2018/03/31 DOTA
使用Python编写简单的画图板程序的示例教程
2015/12/08 Python
十条建议帮你提高Python编程效率
2016/02/16 Python
Flask框架Jinjia模板常用语法总结
2018/07/19 Python
Python使用装饰器模拟用户登陆验证功能示例
2018/08/24 Python
python3调用windows dos命令的例子
2019/08/14 Python
django下创建多个app并设置urls方法
2020/08/02 Python
html5实现的便签特效(实战分享)
2013/11/29 HTML / CSS
英国最大的割草机购买网站:Just Lawnmowers
2019/11/02 全球购物
社区优秀志愿者先进事迹
2014/05/09 职场文书
应届生们该怎么书写求职信?
2019/07/05 职场文书
Python 读写 Matlab Mat 格式数据的操作
2021/05/19 Python
HTML常用标签超详细整理
2022/03/19 HTML / CSS
教你使用Python获取QQ音乐某个歌手的歌单
2022/04/03 Python