我正在尝试将html数据动态插入到动态创建的列表中,但是当我尝试为动态创建的按钮附加onclick事件时,事件不会触发。解决方案将非常感激。
Javascript代码:
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('btnSubmit').addEventListener('click', function () {
var name = document.getElementById('txtName').value;
var mobile = document.getElementById('txtMobile').value;
var html = '<ul>';
for (i = 0; i < 5; i++) {
html = html + '<li>' + name + i + '</li>';
}
html = html + '</ul>';
html = html + '<input type="button" value="prepend" id="btnPrepend" />';
document.getElementsByTagName('form')[0].insertAdjacentHTML('afterend', html);
});
document.getElementById('btnPrepend').addEventListener('click', function () {
var html = '<li>Prepending data</li>';
document.getElementsByTagName('ul')[0].insertAdjacentHTML('afterbegin', html);
});
});
HTML代码:
<form>
<div class="control">
<label>Name</label>
<input id="txtName" name="txtName" type="text" />
</div>
<div class="control">
<label>Mobile</label>
<input id="txtMobile" type="text" />
</div>
<div class="control">
<input id="btnSubmit" type="button" value="submit" />
</div>
</form>
答案 0 :(得分:80)
这是因为你的元素是动态创建的,你应该event delegation来处理事件。
document.addEventListener('click',function(e){
if(e.target && e.target.id== 'brnPrepend'){
//do something
}
});
jquery让它变得更容易:
$(document).on('click','#btnPrepend',function(){//do something})
以下是您可以阅读的有关事件委派event delegation article
的文章答案 1 :(得分:9)
您需要在创建元素后附加事件。喜欢:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('btnSubmit').addEventListener('click', function() {
var name = document.getElementById('txtName').value;
var mobile = document.getElementById('txtMobile').value;
var html = '<ul>';
for (i = 0; i < 5; i++) {
html = html + '<li>' + name + i + '</li>';
}
html = html + '</ul>';
html = html + '<input type="button" value="prepend" id="btnPrepend" />';
document.getElementsByTagName('form')[0].insertAdjacentHTML('afterend', html);
document.getElementById('btnPrepend').addEventListener('click', function() {
var html = '<li>Prepending data</li>';
document.getElementsByTagName('ul')[0].insertAdjacentHTML('afterbegin', html);
});
});
});
<form>
<div class="control">
<label>Name</label>
<input id="txtName" name="txtName" type="text" />
</div>
<div class="control">
<label>Mobile</label>
<input id="txtMobile" type="text" />
</div>
<div class="control">
<input id="btnSubmit" type="button" value="submit" />
</div>
</form>
答案 2 :(得分:9)
通过捕获document.body
上的点击然后检查事件目标,有一种解决方法。
document.body.addEventListener( 'click', function ( event ) {
if( event.srcElement.id == 'btnSubmit' ) {
someFunc();
};
} );
答案 3 :(得分:2)
你可以做类似的事情:
// Get the parent to attatch the element into
var parent = document.getElementsByTagName("ul")[0];
// Create element with random id
var element = document.createElement("li");
element.id = "li-"+Math.floor(Math.random()*9999);
// Add event listener
element.addEventListener("click", EVENT_FN);
// Add to parent
parent.appendChild(element);
答案 4 :(得分:1)
var __ = function(){
this.context = [];
var self = this;
this.selector = function( _elem, _sel ){
return _elem.querySelectorAll( _sel );
}
this.on = function( _event, _element, _function ){
this.context = self.selector( document, _element );
document.addEventListener( _event, function(e){
var elem = e.target;
while ( elem != null ) {
if( "#"+elem.id == _element || self.isClass( elem, _element ) || self.elemEqal( elem ) ){
_function( e, elem );
}
elem = elem.parentElement;
}
}, false );
};
this.isClass = function( _elem, _class ){
var names = _elem.className.trim().split(" ");
for( this.it = 0; this.it < names.length; this.it++ ){
names[this.it] = "."+names[this.it];
}
return names.indexOf( _class ) != -1 ? true : false;
};
this.elemEqal = function( _elem ){
var flg = false;
for( this.it = 0; this.it < this.context.length; this.it++ ){
if( this.context[this.it] === _elem && !flg ){
flg = true;
}
}
return flg;
};
}
function _( _sel_string ){
var new_selc = new __( _sel_string );
return new_selc;
}
现在您可以注册活动了,
_( document ).on( "click", "#brnPrepend", function( _event, _element ){
console.log( _event );
console.log( _element );
// Todo
});
浏览器支持
chrome-4.0,Edge-9.0,Firefox-3.5 Safari-3.2,Opera-10.0及更高版本
答案 5 :(得分:1)
我创建了一个小型图书馆来帮助您:Library source on GitHub
Total 40 (delta 14), reused 0 (delta 0)
error: RPC failed; curl 56 SSLRead() return error -9806
fatal: the remote end hung up unexpectedly
fatal: the remote end hung up unexpectedly
Everything up-to-date
功能类似于jQuery.on()。
该库使用Element.matches()方法针对给定的选择器测试目标元素。触发事件后,仅当目标元素与给定的选择器匹配时,才调用回调。
答案 6 :(得分:1)
我知道这个话题太老了,但是我花了几分钟时间来创建一个非常有用的代码,使用纯JAVASCRIPT
可以很好并且很容易地工作。
这是带有简单示例的代码:
String.prototype.addEventListener=function(eventHandler, functionToDo){
let selector=this;
document.body.addEventListener(eventHandler, function(e){
e=(e||window.event);
e.preventDefault();
const path=e.path;
path.forEach(function(elem){
const selectorsArray=document.querySelectorAll(selector);
selectorsArray.forEach(function(slt){
if(slt==elem){
if(typeof functionToDo=="function") functionToDo(el=slt, e=e);
}
});
});
});
}
// And here is how we can use it actually !
"input[type='number']".addEventListener("click", function(element, e){
console.log( e ); // Console log the value of the current number input
});
<input type="number" value="25">
<br>
<input type="number" value="15">
<br><br>
<button onclick="addDynamicInput()">Add a Dynamic Input</button>
<script type="text/javascript">
function addDynamicInput(){
const inpt=document.createElement("input");
inpt.type="number";
inpt.value=Math.floor(Math.random()*30+1);
document.body.prepend(inpt);
}
</script>
答案 7 :(得分:1)
这是我想出的另一个解决方案。我发现与事件目标相比,这更容易处理,因为如果单击子项,它们不会触发。方法是设置事件监听器并在向文档追加新元素后重置它们:
function listen() {
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener("click", function(){
console.log("Hello World");
});
});
}
listen();
document.body.innerHTML += "<p class='btn'>Click Here 2.0 .</p>";
listen();
<!DOCTYPE html>
<html>
<body>
<p class='btn'>Click Here.</p>
</body>
</html>
编辑: 为避免同一事件的堆叠侦听器,请参阅:Answer
答案 8 :(得分:0)
我为此做了一个简单的功能。
_case
函数使您不仅可以获取目标,还可以获取绑定事件的父元素。
回调函数返回事件,该事件包含目标(evt.target
)和与选择器匹配的父元素(evt._this
)。单击元素后,您可以在此处执行所需的工作。
我还不确定if-else
或switch
哪个更好
var _case = function(evt, selector, cb) {
var _this = evt.target.closest(selector);
if (_this && _this.nodeType) {
evt._this = _this;
cb(evt);
return true;
} else { return false; }
}
document.getElementById('ifelse').addEventListener('click', function(evt) {
if (_case(evt, '.parent1', function(evt) {
console.log('1: ', evt._this, evt.target);
})) return false;
if (_case(evt, '.parent2', function(evt) {
console.log('2: ', evt._this, evt.target);
})) return false;
console.log('ifelse: ', this);
})
document.getElementById('switch').addEventListener('click', function(evt) {
switch (true) {
case _case(evt, '.parent3', function(evt) {
console.log('3: ', evt._this, evt.target);
}): break;
case _case(evt, '.parent4', function(evt) {
console.log('4: ', evt._this, evt.target);
}): break;
default:
console.log('switch: ', this);
break;
}
})
#ifelse {
background: red;
height: 100px;
}
#switch {
background: yellow;
height: 100px;
}
<div id="ifelse">
<div class="parent1">
<div class="child1">Click me 1!</div>
</div>
<div class="parent2">
<div class="child2">Click me 2!</div>
</div>
</div>
<div id="switch">
<div class="parent3">
<div class="child3">Click me 3!</div>
</div>
<div class="parent4">
<div class="child4">Click me 4!</div>
</div>
</div>
希望有帮助!
答案 9 :(得分:0)
区别在于您如何在DOM中创建和附加元素。
如果通过document.createElement
创建一个元素,请添加一个事件侦听器,并将其附加到DOM。您的事件将会触发。
如果您将元素创建为像这样的字符串:html + =“
一种解决方案是使用document.createElement
创建每个元素,然后将它们直接添加到DOM元素中。
// Sample
let li = document.createElement('li')
document.querySelector('ul').appendChild(li)
答案 10 :(得分:0)
我发现 jillykate 发布的解决方案有效,但前提是目标元素嵌套最多。如果不是这种情况,可以通过遍历父母来纠正,即
function on_window_click(event)
{
let e = event.target;
while (e !== null)
{
// --- Handle clicks here, e.g. ---
if (e.getAttribute(`data-say_hello`))
{
console.log("Hello, world!");
}
e = e.parentElement;
}
}
window.addEventListener("click", on_window_click);
还要注意,我们可以按任何属性处理事件,或将侦听器附加到任何级别。上面的代码使用自定义属性和window
。我怀疑各种方法之间是否存在实用上的差异。