我有一个显示自定义对话框的按钮。如果用户选择“取消”,则应从DOM中删除对话框,并且不采取进一步的措施。如果他们单击“开始删除”,则应继续执行代码。
对话框正确显示和隐藏,但是,当我取消并隐藏对话框后,该按钮将不再起作用以再次显示对话框。
我创建了一个使用模板字符串显示弹出窗口的弹出窗口类,然后将其注入到DOM中。弹出窗口在构造函数中接受一个回调,我用它来隐藏弹出窗口。
请参阅以下JS小提琴: https://jsfiddle.net/khgriffi259/vs6r5ake/13/
class Popup {
constructor(title, message, callback) {
this.title = title;
this.message = message;
this.callback = callback;
this.container = document.querySelector('body');
this.result = '';
}
init() {
const popup = `
<div class="popup-wrapper">
<div class="popup bg-white p-1">
<div class="popup-close">X</div>
<div class="popup-content ">
<h2 class="">${this.title}</h2>
<p class="p-1 my-2">${this.message}</p>
<div class="dialogue_buttons my-1">
<button class="btn popup-no" >Cancel</button>
<button class="btn btn-danger my-1 popup-yes" >Start Delete</button>
</div>
</div>
</div>
</div>
`;
this.container.innerHTML += popup;
this.container.querySelector('.popup-no').addEventListener('click', () => this.cancelListener());
this.container.querySelector('.popup-yes').addEventListener('click', () => this.startListener());
}
cancelListener() {
this.result = false;
this.callback();
// if (this.callback !== undefined) {
// this.callback(this.result);
// }
}
startListener() {
this.result = true;
if (this.callback !== undefined) {
this.callback();
}
}
getResult() {
console.log(this.result) ;
return this.result;
}
}
//end of Popup Class
const button = document.querySelector('button');
button.addEventListener('click', e => {
if (e.target.tagName === 'BUTTON') {
const confirmDelete = new Popup(
'Delete',
'This will permanently delete this experience record.',
()=>{
console.log('hello');
let elem = document.querySelector('.popup-wrapper');
elem.parentNode.removeChild(elem);
}
);
confirmDelete.init();
}
})
<button>
click me
</button>
我希望弹出窗口能够隐藏,并且如果用户再次单击该按钮,则该按钮将具有生成新弹出窗口的功能。
答案 0 :(得分:3)
有关代码的固定版本,请参见下文。
唯一的变化是
this.container.innerHTML += popup;
到
this.container.insertAdjacentHTML('beforeend', popup);
您的原始代码失败的原因是.innerHTML
将DOM树序列化回HTML字符串,追加popup
,然后对.innerHTML
的赋值将重新解析整个过程,重新创建所有元素从头开始。副作用是,您的原始click
侦听器会丢失,因为它仍附加到旧的button
元素上。分配给.innerHTML
意味着您将获得一个全新的DOM树。
如the documentation for insertAdjacentHTML
所述:
Element
接口的insertAdjacentHTML()
方法将指定的文本解析为HTML或XML,并将结果节点插入到DOM树中的指定位置。 它不会重新解析正在使用该元素的元素,因此不会破坏该元素内部的现有元素。避免了额外的序列化步骤,使其比直接{{3} }操作。
(强调我的。)
class Popup {
constructor(title, message, callback) {
this.title = title;
this.message = message;
this.callback = callback;
this.container = document.querySelector('body');
this.result = '';
}
init() {
const popup = `
<div class="popup-wrapper">
<div class="popup bg-white p-1">
<div class="popup-close">X</div>
<div class="popup-content ">
<h2 class="">${this.title}</h2>
<p class="p-1 my-2">${this.message}</p>
<div class="dialogue_buttons my-1">
<button class="btn popup-no" >Cancel</button>
<button class="btn btn-danger my-1 popup-yes" >Start Delete</button>
</div>
</div>
</div>
</div>
`;
this.container.insertAdjacentHTML('beforeend', popup);
this.container.querySelector('.popup-no').addEventListener('click', () => this.cancelListener());
this.container.querySelector('.popup-yes').addEventListener('click', () => this.startListener());
}
cancelListener() {
this.result = false;
this.callback();
// if (this.callback !== undefined) {
// this.callback(this.result);
// }
}
startListener() {
this.result = true;
if (this.callback !== undefined) {
this.callback();
}
}
getResult() {
console.log(this.result) ;
return this.result;
}
}
//end of Popup Class
const button = document.querySelector('button');
button.addEventListener('click', e => {
if (e.target.tagName === 'BUTTON') {
const confirmDelete = new Popup(
'Delete',
'This will permanently delete this experience record.',
()=>{
console.log('hello');
let elem = document.querySelector('.popup-wrapper');
elem.parentNode.removeChild(elem);
}
);
confirmDelete.init();
}
})
<button>
click me
</button>
答案 1 :(得分:1)
编辑innerHTML
中的body
时,请清除eventListener
上的button
。
我已经在https://jsfiddle.net/n5k9rsbe/6/
中将小提琴更新为工作版本。有两种方法可以使它起作用:
1-创建一个容器元素并对其进行修改
<div id="container"></div>
JavaScript:
document.querySelector('#container').innerHTML = '...';
2-在appendChild
上使用body
const elem = document.createElement('div');
elem.innerHTML = popup
this.container.appendChild(elem)