使用一次后,所有按钮均失效

时间:2019-05-11 20:33:23

标签: javascript dom

我有一个显示自定义对话框的按钮。如果用户选择“取消”,则应从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>

我希望弹出窗口能够隐藏,并且如果用户再次单击该按钮,则该按钮将具有生成新弹出窗口的功能。

2 个答案:

答案 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)