我想不少人都会向我同样曾经被动态添加元素的事件绑定困惑好久,也就是在页面加载完成后给已有元素绑定了事件,但又新增长的元素上却没有绑定任何事件。 css
js的事件监听跟css不同,css只要设定好了样式,不管是原来就有的仍是新添加的,都有同样的表现。而事件监听不是,你必须给每个元素单独绑定事件。 html
常见的例子是处理表格的时候。每行行末有个删除按钮,点了这个可以删除这一行。 app
一般,我会这么绑定 dom
对于在domready以前就存在的删除按钮,一切都很完美。但若是在domready以后用js动态添加几行,那新增的几行中的这些按钮都将失去任何做用。 函数
如何解决这个问题?如下提供4种解决方案:
=============================
0号解决方案——onclick法
若是不顾结构与行为分离的准则的话,一般,我会这么作。
注意,此时的deltr这个function必须是全局函数,得放jQuery(function($) {})外面,放里边就成局部函数了,html里的onclick就调用不到了! 测试
=============================
1号解决方案——重复绑定法
即,在domready的时候就给已有的元素绑定事件处理函数,
然后当新增长的元素的时候再次绑定。 this
=============================
2号解决方案——事件冒泡法
利用事件冒泡的原理,咱们给这个按钮的祖先元素绑定事件处理函数。
而后经过event.target这个对象来判断,这个事件是否是咱们要找的对象触发的。
一般能够利用一些DOM属性,好比event.target.className、event.target.tagName等之类的来判断。 spa
=============================
总评:
上面4种方案,各有优劣。
0号方案,结构与行为彻底没有分离,并且污染全局命名空间。最不推荐。因此我都不把它看成一个方案来看。但对于js初学者,能够用来项目救急。
1号方案,中规中矩,没啥好也没啥很差
2号方案,这种方法充分的发挥了js事件冒泡的优点。并且效率最高。但同时因为这种方案无视了jQuery强大的选择器,因此若是涉及的元素属性要求过多就会比较麻烦了。你会徘徊在众多if的条件的是非关系之中。后来我想起来,能够用jQuery中的$(event.target).is(selector)来做为条件。这样能够极大提高开发效率,但略微下降执行效率。
3号方案,这是我认为最能体现结构与行为分离的思想的一种方案。但缺点也很明显,对于jQuery依赖性过于高了,要不就本身写一个复制连同事件一块儿复制的函数,但这也显然对于初学者来讲异常困难。但从将来的趋势的角度来看,仍是很推荐使用这种方案的。 插件
具体选用哪个方案,没有定数。具体看你的项目以及你js还有结构与行为分离的思想的掌握程度。最适合的才是最好的。 code
=============================
附加:
把3号方案改形成完美的结构行为分离的样式。
首先,带有template的是模板元素。他是一切复制的源泉,为了防止被误删,因此设为不可见。若是不会删除光,那么这个模板元素也是可选的。由于你能够复制任何一个已经存在的用于循环元素。
其次,给每一个重复的元素加上一个repeat,方便用于删除按钮找到这一级元素。这个是可选的,有时候并不须要。
最后是给每个要修改的元素加上一个类,便于用find找到。好比我这里就家了content类,新增长的能够修改里边的值。
这样一个完美的结构与行为分离的案例就完成了。
一样,这段js也适用于以下的html结构
其余动态绑定事件的方法:
$("#table").on('click', 'button.del', function(e) {
alert('绑定事件了');
});//做用:测试在动态添加的<tr>上设置一个删除按钮的可行性,"test"是button的一个class,"#table"是table的id.
on(events,[selector],[data],fn) events:一个或多个用空格分隔的事件类型和可选的命名空间,如"click"或"keydown.myPlugin" 。 selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代。若是选择器为null或省略,当它到达选定的元素,事件老是触发。 data:当一个事件被触发时要传递event.data给事件处理函数。 fn:该事件被触发时执行的函数。 false 值也能够作一个函数的简写,返回false。 替换bind() 当第二个参数'selector'为null时,on()和bind()其实在用法上基本上没有任何区别了,因此咱们能够认为on()只是比bind()多了一个可选的'selector'参数,因此on()能够很是方便的换掉bind()