现在的位置: 首页 > 综合 > 正文

绑定事件

2018年05月27日 ⁄ 综合 ⁄ 共 5202字 ⁄ 字号 评论关闭

我想很多人都会向我一样曾经
被新元素的事件绑定困惑很久也就是
在页面加载完成后给元素绑定了事件,但又新增加的元素上却没有绑定任何事件。

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


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

<
table
>

    

<
tbody
>

        

<
tr
>

        
   

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

            

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

        

</
tr
>

        

<
tr
>

            

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

            

<
td
><
button
class
=
"
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
    ><
    button
    onclick
    =
    "
    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
    ><
    button
    class
    =
    "
    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
    ><
    button
    class
    =
    "
    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. <
    tr
    class
    =
    "
    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. <
    table
    id
    =
    "
    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. <
    ul
    id
    =
    "
    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
    >
【上篇】
【下篇】

抱歉!评论已关闭.