正文 6486字数 362,020阅读

在 JS 中动态添加事件,涉及到浏览器兼容性问题。结合我的实践经验以及从网上收集的一些资料,特整理在此,希望有点用。

方法一、setAttribute
var obj = document.getElementById("obj"); obj.setAttribute("onclick", "javascript:alert('测试');");
Run code
Cut to clipboard

    这里利用 setAttribute 指定 onclick 属性, 但是:用 setAttribute 设置 style、onclick、onmouseover 这些属性在 IE 中是行不通的。但是某些属性可以,以下是通过测试的一个例子:
    如果你知道某个控件如select控件的name,但是这个控件并没有设置id属性,这时候在IE下测试发现如果仅仅通过控件的name是无法给它动态添加属性和事件的,因为W3C是允许name属性重复的。
    function test(){ //通过tag,获得所有tagName为select的控件,返回的是一个select集合 var obj=document.getElementByTagName(“select”); //通过obj.length获得select集合的个数,在挨个匹配name for(var i=0;i<obj.length;i++){ //找到name为part的select控件 if(obj[i].name==’part’){ obj[i].setAttribute(“id”,”myid”);//为name为part的select控件设置id为myid obj[i].setAttribute(“onchange”,myfunc); //为该控件设置onchange事件,即调用myfunc函数 } } } function myfunc(){ alert(“test ok!”); }
    Run code
    Cut to clipboard


      方法二、用 attachEvent 和 addEventListener
      IE支持attachEvent
      obj.attachEvent("onclick", Foo); function Foo() { alert("测试"); }
      Run code
      Cut to clipboard

        也可写在一起
        obj.attachEvent("onclick", function(){alert("测试");});
        Run code
        Cut to clipboard

          其它浏览器支持 addEventListener
          obj.addEventListener("click", Foo, false); function Foo() { alert("测试"); }
          Run code
          Cut to clipboard

            同样也可写在一起
            obj.addEventListener("click", function(){alert("测试");}, false);
            Run code
            Cut to clipboard

              注意 attachEvent 的事件带 on,如 onclick,而 addEventListener 不带 on,如 click。
              顺便说一下 addEventListener 的第三个参数(虽然很少用) useCapture - 如果为 true,则 useCapture 指示用户希望启动捕获。启动捕获后,所有指定类型的事件将在被指派到树中其下面的任何 EventTargets 之前指派给已注册的 EventListener。正在通过树向上 bubbling 的事件将不触发指定的使用捕获的 EventListener。
              综合应用
              var obj = document.getElementById("obj"); if(window.addEventListener){ //其它浏览器的事件代码: Mozilla, Netscape, Firefox //添加的事件的顺序即执行顺序 obj.addEventListener('click', alert('test1'), false); obj.addEventListener('click', alert('test2'), false); } else { //IE 的事件代码 obj.attachEvent('onclick', function(){alert('test3');}); obj.attachEvent('onclick', function(){alert('test4’);}); }
              Run code
              Cut to clipboard


                方法三、事件 = 函数
                例:obj.onclick = Foo;
                这在多个浏览器中均支持,这是属于旧的规范(方法二属于 DOM2 的规范),不过由于使用方便,用的场合也比较多。

                以前经常使用document.getElementByID取得html里面ID标记的属性,昨天想当然使用document.getElementByName(注意没有s),来获取name标记的属性,结果发现浏览器报错。查了查资料,才发现没有这个函数,应该是getElementsByName。和document.getElementByID不同的是,前者返回的是一个name和ID的集合,因为W3C是允许name属性重复的,也就是html标记可以使用同一个name名字,而后者返回了ID的第一个元素。所以document.getElementsByName的使用方法往往是document.getElementsByName("***")[0], [1]等。document.getElementsByTagName, document.formName.elements 这类方法所得到的结果也都是集合。
                <input type=checkbox value=2>2 <input type=checkbox value=1>1 <script language=”javascript”> var arr = document.getElementsByTagName("input"); //取得所有input,返回就是数组. alert(arr[0].value); //取第一个input的值. </script>
                Run code
                Cut to clipboard


                  再给个例子:
                  一个Table中有7,8个tr,我需要动态的将其中4,5个tr display=none/block。但是我又不想给每个tr都定义一个id,所以我想到了给这4,5个tr一个共同的name然后用 getElementsByName来返回一个数组,这样用循环操作每一个tr方便点,可是后来发现ie不支持。
                  如果只是 hide/show 操作的话,可以设一个独立 stylesheet,把同一 classname 的 object 设为 display:none。之后便可以透过改变这个 stylesheet 的 disabled property 改变属于这 classname 的 object 的 show/hide 状况。
                  <html> <head> <title>test</title> </head> <body> <style id="abc-style"> .abc {display: none} </style> <h1 class='abc'>test</h1> <script> function toggle() { var style = document.getElementById('abc-style'); style.disabled = !style.disabled; } </script> <P onclick="toggle()">click me </p> </body> </html>
                  Run code
                  Cut to clipboard

                    延伸思考:

                    比如说,你想得到所有class属性是"abc"的tr,用这个就可以了:
                    代码:
                    alltr = document.evaluate("//tr[@class='abc']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0; i < alltr.snapshotLength; i++) { tr = alltr.snapshotItem(i); // do something with tr }
                    Run code
                    Cut to clipboard




                      、、============================================



                      最简单的是这样:
                      <input type="button" onclick="alert(this.value)" value="我是 button" />
                      Run code
                      Cut to clipboard

                        动态添加onclick事件:
                        <input type="button" value="我是 button" id="bu"> <script type="text/javascript"> var bObj=document.getElementById("bu"); bObj.onclick= objclick; function objclick(){alert(this.value)}; </script>
                        Run code
                        Cut to clipboard

                          如果使用匿名函数 function(){},则如下面所示:
                          <input type="button" value="我是 button" id="bu"> <script type="text/javascript"> var bObj=document.getElementById("bu"); bObj.onclick=function(){alert(this.value)}; </script>
                          Run code
                          Cut to clipboard

                            上面的方法其实原理都一样,都是定义 onclick 属性的值。值得注意的是,如果多次定义 obj.onclick,例如:obj.onclick=method1; obj.onclick=method2; obj.onclick=method3,那么只有最后一次的定义obj.onclick=method3才生效,前两次的定义都给最后一次的覆盖掉了。
                            再看 IE 中的 attachEvent:
                            <input type="button" value="我是拉登" id="bu"> <script type="text/javascript"> var bObj = document.getElementById("bu"); bObj.attachEvent("onclick",method1); bObj.attachEvent("onclick",method2); bObj.attachEvent("onclick",method3); function method1(){alert("第一个alert")} function method2(){alert("第二个alert")} function method3(){alert("第三个alert")} </script>
                            Run code
                            Cut to clipboard

                              执行顺序是 method3 > method2 > method1 ,先进后出,与堆栈中的变量相似。需要注意的是attachEvent 中第一个参数是on开头的,可以是 onclick/onmouseover/onfocus 等等
                              据说(未经确认验证)在 IE 中使用 attachEvent 后最好再使用 detachEvent 来释放内存
                              再看看 Firefox 中的的 addEventListener:
                              <input type="button" value="我是布什" id="bu"> <script type="text/javascript"> var bObj = document.getElementById("bu"); bObj.addEventListener("click",method1,false); bObj.addEventListener("click",method2,false); bObj.addEventListener("click",method3,false); function method1(){alert("第一个alert")} function method2(){alert("第二个alert")} function method3(){alert("第三个alert")} </script>
                              Run code
                              Cut to clipboard

                                可以看到,在 ff 中的执行顺序是 method1 > method2 > method3 , 刚好与 IE 相反,先进先出。需要注意的是 addEventListener 有三个参数,第一个是不带“on”的事件名称,如 click/mouseover/focus等。