javascript - 使用一次后所有按钮都失去功能

标签 javascript dom

我有一个显示自定义对话框的按钮。如果用户选择“取消”,则应从 DOM 中删除该对话框,并且不采取进一步的操作。如果他们单击“开始删除”,则应继续执行代码。

对话框正确显示和隐藏,但是,在我取消并隐藏对话框后,该按钮不再起作用以再次显示对话框。

我创建了一个弹出类,它使用模板字符串来显示弹出窗口,然后将其注入(inject)到 DOM 中。弹出窗口在构造函数中接受回调,我用它来隐藏弹出窗口。

请参阅以下 JS Fiddle: 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>

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

最佳答案

请参阅下面的代码的固定版本。

唯一的变化是

this.container.innerHTML += popup;

this.container.insertAdjacentHTML('beforeend', popup);

原始代码失败的原因是 .innerHTML 将 DOM 树序列化回 HTML 字符串,附加 popup,然后分配给 .innerHTML 重新解析整个事情,从头开始重新创建所有元素。副作用是,您原来的 click 监听器会丢失,因为它仍然附加到旧的 button 元素。分配给 .innerHTML 意味着您将获得一棵全新的 DOM 树。

the documentation for insertAdjacentHTML状态:

The insertAdjacentHTML() method of the Element interface parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position. It does not reparse the element it is being used on, and thus it does not corrupt the existing elements inside that element. This avoids the extra step of serialization, making it much faster than direct innerHTML manipulation.

(强调我的。)

  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>

关于javascript - 使用一次后所有按钮都失去功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56094080/

相关文章:

javascript - WEBRTC 可以使用共同浏览功能吗?

javascript - HTML5 Canvas + JS 库中的选择/拖放功能?

Java DOM : Get all parents list

java - 使用 Selenium 提取 DOM 属性值

javascript - 导入,需要吗?如何将 Javascript 文件混合在一起?

php - 单击链接时转到上一个网页

javascript - SVG 对象的实时迭代

java - 在 JAVA 中处理包含 XML 的字符串的最有效方法

html - 对于大量文件,一种将每个 DOM 节点的计算样式记录到文件的优雅方法?

javascript - 使用输入控件动态操作元素属性?