为元素添加class ,无法绑定事件?

polandeme
  • 74
<!doctype html>
<html>
    <head>
        <title> game </title>
        <style>
            td {
                width: 60px;
                height: 60px;
                text-align: center;
            }
            .active {
                background: red;
            }
        </style>
    </head>
    <body>
        <table border="1" cellspacing="0">
            <tr>
                <td>dsde</td>
                <td>dsdd</td>
                <td>dsdsw</td>
            </tr>
            <tr>
                <td>ds</td>
                <td>ds</td>
                <td>ds</td>
            </tr>
            <tr>
                <td>ds </td>
                <td>ds </td>
                <td>ds</td>
            </tr>
        </table>
        <script src="../lib/jquery-2.1.0.min.js"></script>
        <script>
            function cell(i,j) {
                var tr = $("tr").eq(i);
                return tr.children("td").eq(j);
            }
            cell(1,1).addClass('active');
            $(".active").on('click',function(){
                    $(this).removeClass('active');
                    var i = Math.round(Math.random() * 2);
                    var j = Math.round(Math.random() * 2);
                    cell(i,j).addClass('active');
                    });
        </script>
    </body>
</html>

为什么addclass之后,active没有绑定click事件。

回复
阅读 13.7k
7 个回答
✓ 已被采纳

利用事件委托的写法是

$("table").on('click','.active',function(){
  $(this).removeClass('active');
  var i = Math.round(Math.random() * 2);
  var j = Math.round(Math.random() * 2);
  cell(i,j).addClass('active');
});

用事件委托的意思是table下面所有叫active的class都触发这个事件,事件绑定在table上面,
而你之前的写法事件绑定在第一个.active上面,后面随机的td没有绑定事件,所以只有第一次生效。
测试地址

http://jsbin.com/heteta/1/edit?html,css,js,output

题主,想象下这个过程。
js代码在载入后,只会自动运行一次。所以是不会一直监视着题主的DOM的!
这样在代码运行时,只会将你的事件,绑定在那个瞬间,在DOM树中类名为active的DOM元素上(不要被JQuery的选择器表达式迷惑了,事件绑定最终还是要回到DOM元素上)。
所以楼主的写法只是将事件绑定在事件绑定时唯一有active类名的那个DOM元素上了!这就是其他元素没有反应的原因。
正确的绑定方法就是事件委托 @TomDong 已经给出解释,@StephenLee 也给出代码咯。
建议楼主有时间的话多了解一下javascript的实现机制:)

数趣
  • 1
新手上路,请多包涵

$('table').on('click','.active',function(){})

@TomDong 喵哥所言,这里应该使用事件委托机制。

<!doctype html>
<html>
    <head>
        <title> game </title>
        <style>
            td {
                width: 60px;
                height: 60px;
                text-align: center;
            }
            .active {
                background: red;
            }
        </style>
    </head>
    <body>
        <table border="1" cellspacing="0">
            <tr>
                <td>dsde</td>
                <td>dsdd</td>
                <td>dsdsw</td>
            </tr>
            <tr>
                <td>ds</td>
                <td>ds</td>
                <td>ds</td>
            </tr>
            <tr>
                <td>ds </td>
                <td>ds </td>
                <td>ds</td>
            </tr>
        </table>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
        <script>
            function cell(i,j) {
                var tr = $("tr").eq(i);
                return tr.children("td").eq(j);
            }
            cell(1,1).addClass('active');
            $("table").on('click','.active',function(){
              $(this).removeClass('active');
              var i = Math.round(Math.random() * 2);
              var j = Math.round(Math.random() * 2);
              cell(i,j).addClass('active');
            });
        </script>
    </body>
</html> 

我写过一篇介绍 javascript 的事件委托的博文,jQuery 只是对其进行了包装,原理是想通的,题主不妨一读:《Javascript - 事件委托是怎么工作的?》

.on( events [, selector ] [, data ], handler(eventObject) )
events
Type: String
One or more space-separated event types and optional namespaces, such as "click" or "keydown.myPlugin".
selector
Type: String
A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element.

官方文档里有说,当selector为null的时候,其将一直指向$(".active"),由于你一开始$(".active")就是最中间的那个元素,所以它一直都不会变,其相当于click事件

  1. $(".active").on('click',function(){........});这样写的意思是,dom加载完毕时候, 给.active添加单击事件,仅此而已。
  2. 但是你要求的是在交互过程中,实时监听有.active元素,并添加click事件。
  3. 解决方案:将侦听事件绑在要监听的元素(td)的父级元素(table)上。此父级元素要保证交互过程中不会被清除。否则监听失败。
  4. 原理:javascript事件机制:捕获-冒泡。再具体即事件代理。懂代码更要懂原理。

关于“将侦听事件绑在要监听的元素的父级元素上”,举一个例子:$("#comment-form").on("click", ".addNew", addComment),和$("body").on("click", "#comment-form .addNew", addComment)这两种写法都可以完成同样的功能。但是“定义”on函数本身前者要比后者费时(因为查找#comment-form要比查找body费时),所以说,如果想节省首次进入页面的js的加载时间就用后者,但那样的话每次发生click事件,查找的耗时就会多,如何权衡就要看实际业务了。

宣传栏