jquery 新建的元素事件绑定问题

js的事件监听跟css不一样,css只要设定好了样式,不论是原来就有的还是新添加的,都有一样的表现。而事件监听不是,你必须给每一个元素单独绑定事件。

常见的例子是处理表格的时候。每行行末有个删除按钮,点了这个能够删除这一行。

<table>
  
 <tbody>
  
   
 <tr>
  
       
 <td>这行原来就有</td>
  
       
 <td><buttonclass="del">删除</button></td>
  
   
 </tr>
  
   
 <tr>
  
       
 <td>这行原来就有</td>
  
       
 <td><buttonclass="del">删除</button></td>
  
   
 </tr>
  
 </tbody>
</table>

通常,我会这么绑定

  1. jQuery(function($){

  2. //已有删除按钮初始化绑定删除事件

  3. $(".del").click(function() {

  4. $(this).parents("tr").remove();

  5. });

  6. });

对于在domready之前就存在的删除按钮,一切都很完美。但如果在domready之后用js动态添加几行,那新增的几行中的这些按钮都将失去任何作用。

如何解决这个问题?以下提供4种解决方案:
=============================
0号解决方案——onclick法
如果不顾结构与行为分离的准则的话,通常,我会这么做。
注意,此时的deltr这个function必须是全局函数,得放jQuery(function($)
{})外面,放里边就成局部函数了,html里的onclick就调用不到了!

  1. <td><buttononclick="deltr(this)">删除</button></td>

  1. jQuery(function($){

  2. //添加行

  3. $("#add2").click(function(){

  4. $("#table2>tbody").append(‘<tr><td>新增行</td><td><button
    nclick="deltr(this)">删除</button></td></tr>‘)

  5. });

  6. });

  7. //删除行的函数,必须要放domready函数外面

  8. function deltr(delbtn){

  9. $(delbtn).parents("tr").remove();

  10. };

=============================
1号解决方案——重复绑定法
即,在domready的时候就给已有的元素绑定事件处理函数,
而后当新增加的元素的时候再次绑定。

  1. <td><buttonclass="del">删除</button></td>

  1. jQuery(function($){

  2. //定义删除按钮事件绑定

  3. //写里边,防止污染全局命名空间

  4. function deltr(){

  5. $(this).parents("tr").remove();

  6. };

  7. //已有删除按钮初始化绑定删除事件

  8. $("#table3
    .del").click(deltr);

  9. //添加行

  10. $("#add3").click(function(){

  11. $(‘<tr><td>新增行</td><td><button
    class="del">删除</button></td></tr>‘)

  12. //在这里给删除按钮再次绑定事件。

  13. .find(".del").click(deltr).end()

  14. .appendTo($("#table3>tbody"));

  15. });

  16. });

=============================
2号解决方案——事件冒泡法
利用事件冒泡的原理,我们给这个按钮的祖先元素绑定事件处理函数。
然后通过event.target这个对象来判断,这个事件是不是我们要找的对象触发的。
通常可以利用一些DOM属性,比如event.target.className、event.target.tagName等之类的来判断。

  1. <td><buttonclass="del">删除</button></td>

  1. jQuery(function($){

  2. //第四个表格的删除按钮事件绑定

  3. $("#table4").click(function(e) {

  4. if (e.target.className=="del"){

  5. $(e.target).parents("tr").remove();

  6. };

  7. });

  8. //第四个表格的添加按钮事件绑定

  9. $("#add4").click(function(){

  10. $("#table4>tbody").append(‘<tr><td>新增行</td><td><button
    class="del">删除</button></td></tr>‘)

  11. });

  12. });
3号解决方案——复制事件法
上面几种方案可以说即便你没有用到jQuery库,你也能相对比较容易的实现。但这种方案相对依赖jQuery的程度更高。而且必须要求jQuery
1.2版以上。低版本jQuery需要插件。
上面两个方案都是对删除函数动了很多脑筋,换了多种触发、绑定的方式。这个方案不同,可以与平时纯静态的元素一样在domready的时候绑定。但在我们添加新行的时候我们改动一下,不再想上面那样拼接字符串来添加新行了。这回我们尝试使用复制DOM元素的方式。并且复制的时候连同绑定的事件一起复制,复制完之后再用find之类的修改内部的元素。
同时,就像这个例子,如果你会把所有元素都删除光,那template这个模板是必须的,如果不会删光,那就未必需要用template了。为了防止被误删,此处我把template设了隐藏。
我使用了jQuery中特有的clone(true)

  1. .template{display:none;}

  1. <trclass="template">

  2. <td>这里是模板</td>

  3. <td><button class="del">删除</button></td>

  4. </tr>

  5. <tr>

  6. <td>这行原来就有</td>

  7. <td><button class="del">删除</button></td>

  8. </tr>

  9. <tr>

  10. <td>这行原来就有</td>

  11. <td><button class="del">删除</button></td>

  12. </tr>

  1. jQuery(function($){

  2. //第五个表格的删除按钮事件绑定

  3. $("#table5
    .del").click(function() {

  4. $(this).parents("tr").remove();

  5. });

  6. //第五个表格的添加按钮事件绑定

  7. $("#add5").click(function(){

  8. $("#table5>tbody>tr:eq(0)")

  9. //连同事件一起复制

  10. .clone(true)

  11. //去除模板标记

  12. .removeClass("template")

  13. //修改内部元素

  14. .find("td:eq(0)")

  15. .text("新增行")

  16. .end()

  17. //插入表格

  18. .appendTo($("#table5>tbody"))

  19. });

  20. });

=============================
总评:
上面4种方案,各有优劣。
0号方案,结构与行为完全没有分离,而且污染全局命名空间。最不推荐。所以我都不把它当作一个方案来看。但对于js初学者,可以用来项目救急。
1号方案,中规中矩,没啥好也没啥不好
2号方案,这种方法充分的发挥了js事件冒泡的优势。而且效率最高。但同时由于这种方案无视了jQuery强大的选择器,所以如果涉及的元素属性要求过多就会比较麻烦了。你会徘徊在众多if的条件的是非关系之中。后来我想起来,可以用jQuery中的$(event.target).is(selector)来作为条件。这样可以极大提升开发效率,但略微降低执行效率。
3号方案,这是我认为最能体现结构与行为分离的思想的一种方案。但缺点也很明显,对于jQuery依赖性过于高了,要不就自己写一个复制连同事件一起复制的函数,但这也显然对于初学者来说异常困难。但从未来的趋势的角度来看,还是很推荐使用这种方案的。

具体选用哪一个方案,没有定数。具体看你的项目以及你js还有结构与行为分离的思想的掌握程度。最适合的才是最好的。

=============================
附加:
把3号方案改造成完美的结构行为分离的样式。
首先,带有template的是模板元素。他是一切复制的源泉,为了防止被误删,所以设为不可见。如果不会删除光,那么这个模板元素也是可选的。因为你可以复制任何一个已经存在的用于循环元素。
其次,给每个重复的元素加上一个repeat,方便用于删除按钮找到这一级元素。这个是可选的,有时候并不需要。
最后是给每一个要修改的元素加上一个类,便于用find找到。比如我这里就家了content类,新增加的可以修改里边的值。
这样一个完美的结构与行为分离的案例就完成了。

  1. <tableid="table6">

  2. <tbody id="tbody6">

  3. <tr class="template
    repeat">

  4. <td class="content">这里是模板</td>

  5. <td><button class="del">删除</button></td>

  6. </tr>

  7. <tr class="repeat">

  8. <td class="content">这行原来就有</td>

  9. <td><button class="del">删除</button></td>

  10. </tr>

  11. <tr class="repeat">

  12. <td class="content">这行原来就有</td>

  13. <td><button class="del">删除</button></td>

  14. </tr>

  15. </tbody>

  16. <tfoot>

  17. <tr>

  18. <td>&nbsp;</td>

  19. <td><button id="add6">添加</button></td>

  20. </tr>

  21. </tfoot>

  22. </table>

  1. jQuery(function($){

  2. //第六个表格的删除按钮事件绑定

  3. $("#tbody6
    .del").click(function() {

  4. $(this).parents(".repeat").remove();

  5. });

  6. //第六个表格的添加按钮事件绑定

  7. $("#add6").click(function(){

  8. $("#tbody6>.template")

  9. //连同事件一起复制

  10. .clone(true)

  11. //去除模板标记

  12. .removeClass("template")

  13. //修改内部元素

  14. .find(".content")

  15. .text("新增行")

  16. .end()

  17. //插入表格

  18. .appendTo($("#tbody6"))

  19. });

  20. });

同样,这段js也适用于如下的html结构

  1. <ulid="tbody6">

  2. <li class="template
    repeat">

  3. <span class="content">这里是模板</span>

  4. <span><button class="del">删除</button></span>

  5. </li>

  6. <li class="repeat">

  7. <span class="content">这行原来就有</span>

  8. <span><button class="del">删除</button></span>

  9. </li>

  10. <li class="repeat">

  11. <span class="content">这行原来就有</span>

  12. <span><button class="del">删除</button></span>

  13. </li>

  14. </ul>

<script type="text/javascript"></script>

时间: 2024-11-10 16:21:58

jquery 新建的元素事件绑定问题的相关文章

jquery 新建的元素事件绑定问题[转]

原文:http://www.cnblogs.com/linzheng/archive/2010/10/17/1853568.html js的事件监听跟css不一样,css只要设定好了样式,不论是原来就有的还是新添加的,都有一样的表现.而事件监听不是,你必须给每一个元素单独绑定事件. 常见的例子是处理表格的时候.每行行末有个删除按钮,点了这个能够删除这一行. <table>    <tbody>        <tr>            <td>这行原来就

工作积累(六)——jQuery实现DOM元素事件绑定

用 jQuery 为DOM元素绑定事件时,如果用下面这种方式: <button class="dynamic-bind">按钮一</button> $(function() {   $('.dynamic-bind').on('click', function(e) {     alert(e.type); //'click' }); }); 那么如果在绑定事件之后通过 jQuery 添加与该选择器相同的新的DOM元素: $('.dynamic-bind:las

jQuery查看dom元素上绑定的事件列表

作为技术狂热分子的职业本能,看到一个技术产品的功能,总会忍不住想知道它是怎么被实现的.比如我每每看到别人网站一个很炫的界面或者很酷的功能,就忍不住打开了浏览器的控制台... 好,不扯远,说说当你想看到网站上某个元素绑定的事件函数的代码时应该怎么做吧. 查看原生绑定的事件函数代码 所谓原生就是通过addEventListener方法绑定到dom元素上.这个好办: 审查绑定事件的元素(对着它右键->审查元素) 在弹出的Elements视图的控制台,右侧点击“Event Listeners”页签 然后

Jquery 在动态元素上绑定事件

弄了很久却没有弄出来,感觉没有错,但是动态元素上的事件根本就不响应,代码如下: <input type="button" id="btnyes" value="确定" /> <div id="divcontent"> </div> <script> $(function () { $("#btnyes").on("click", funct

jQuery挖源码——事件绑定

jQuery版本:2.1.4 最常用事件绑定bind,调用了on. 1 bind: function( types, data, fn ) { 2 return this.on( types, null, data, fn ); 3 } 对应解绑unband,调用了off. 1 unbind: function( types, fn ) { 2 return this.off( types, null, fn ); 3 } 只执行一次的one绑定,赤裸裸调用on. 1 one: function

jQuery的4种事件绑定方法

jQuery中提供了四种绑定事件的方法,分别是bind.live.delegate.on,对应的解除监听的函数分别是unbind.die.undelegate.off: 一.on()方法(首选方法) on() 方法在被选元素及子元素上添加一个或多个事件处理程序. 自 jQuery 版本 1.7 起,on() 方法是 bind().live() 和 delegate() 方法的新的替代品.该方法给 API 带来很多便利,我们推荐使用该方法,它简化了 jQuery 代码库. 参数: event:必需

关于jquery on方法进行事件绑定触发次数指数叠加的问题

发生环境: $modal.on('click', '#search',function(e){}); 上面代码的语法是这样的: .on( events [, selector ] [, data ], handler(eventObject) ) 其中$modal为父容器,在该容器上绑定click事件,当id为search的button被点击时才触发function 存在问题: 1. 点击第一次触发一次 2. 点击第二次触发两次 3. 点击第三次触发四次 ... 以此类推成指数增长 问题原因:o

jquery中的DOM事件绑定与解绑

在jquery事件中有时候有的事件只需要在绑定后有效触发一次,当通过e.target判断触发条件有效触发后解除绑定事件,来避免多次无效触发和与未知情况造成冲突. 这时候就要用到了jquery中的事件绑定与事件解绑. 1 $(document).on('click.endEdit',function (e) { 2 if(!$(e.target).hasClass('datagrid-cell')&&e.target.tagName!="TD"){ //事件发生后的判断条

js元素事件绑定与解绑

为元素绑定事件有3种方式: 1.最常见的绑定方式: document.getElementById("btn").onclick=function(){}; 2.非IE浏览器     element.addEventListener(type,fn,false) (布尔值====true表示捕获,false表示冒泡,一般用false): document.getElementById("btn").addEventListener("click"