【问题标题】:How to remove the DOM elements of a modal on close如何在关闭时删除模式的 DOM 元素
【发布时间】:2020-01-16 23:29:09
【问题描述】:

背景:在撰写本文时,Fomantic-UI 是 Semantic-UI 的实时开发分支,有朝一日将被纳入 Semantic-UI,同时也是事实上支持的 Semantic-UI 属。

问题:Fomantic-UI 提供模态功能 - 只需在 JQuery 元素上调用 .modal() 等等。但是,当模式关闭时,模式元素的 DOM 元素仍然隐藏在 DOM 中。我的用例需要删除这些元素,但我担心模态功能的“剩余”接线。

研究完成:FUI documentation on modals 很有用,但它是从建立一个模态的角度编写的,而不是干净利落地把它取下来。

复制:下面的 sn-p 是一种基于代码的方法,用于为按钮侦听器创建模式和连接。单击按钮打开模式,然后单击关闭按钮。两秒钟后,将显示剩余的 DOM 模态元素的简单 JQuery 计数 - 它应该为零,但将为 1。

注意事项:

1 - FUI 模态有一个令人沮丧的功能,即在单击任何按钮时自动关闭模态。它有一个保存子句,即如果触发的按钮事件处理程序返回 false,则模式保持打开状态。显然,如果您正在进行表单验证等,您需要知道这一点。此外,如果您希望覆盖所有按钮的默认功能,请从 onHide 函数返回 false,例如

element.modal('setting', 'onHide', function(){ return false; });
element.modal('show');

2 - 此 sn-p 使用 FUI 的“dist”版本。由于 FUI 经常更改,因此如果您看到 sn-p 时已经发生了重大更改,则它可能会失败。在撰写本文时,jsdelivr cdn 上的官方版本是 2.8.3。 (2020 年 1 月 17 日编辑)。

var fnSpecial = function(){
	console.log('Close button click function - return true to hide');
  // ... do function activity here....
  return true;
}

$('#b1').on('click', function(){
	
  makeModal({
  	title: 'I be modal',
    content: 'Modal be I !',
    actions: [
      { text: 'Close', fn: fnSpecial}, // for more buttons in the modal add more entries here. 
    ]    
  })

})



function makeModal(opts){
  // create your modal element - I grab the modal template
  var tplt = $('#modalTemplate').html();

  // defaults for modal create
  var obj = {
    title: 'No title !',
    content: 'No content',
    actions: [
    ]
  }

  // Merge the above defaults with the user-supplied options
  obj = $.extend(obj, opts);

  // Apply modal options to the soon-to-be modal element 
  var ele = $(tplt);
  ele.find('.modalHeading').html(obj.title);
  ele.find('.modalBody').html(obj.content);
  ele.addClass('modalContentCopy');

	var modalButtons = ele.find('.modalButtons');
	for (var i =0, max = obj.actions.length; i < max; i = i + 1 ){
  
  	var btn = $('<button >' + obj.actions[i].text + '</button>');
    var fn = obj.actions[i].fn;
    btn.data('fn', fn); // store the callback on the element to avoid closures.
    
    btn.appendTo(modalButtons);
    
    btn.on('click', function(e){    
    	var fn = $(this).data('fn');
      
      if (typeof fn === "function"){
      
        var hide = fn(); // IMPORTANT: the function triggered for the button must return true to close the modal or false to keep it open !

        console.log('Button says hide=' + hide)

        if (hide){

            ele.modal('destroy');
            ele.modal('hide');

              $('#info')
                .html('***');
                
            // wait 2 secs and see if the DOM element has gone
            setTimeout( function(){
              var num = $('.modalContentCopy').length;
              $('#info')
                .html(num)
                .css({ backgroundColor: (num === 0 ? 'lime' : 'red')});
              }, 2000);
        }
      }
      
    });  
  }

	// Simple example of how to reveal the modal element as a f-ui modal 
  ele
    .appendTo($('body'))
    .modal('setting', 'transition', "vertical flip")
	.modal('setting', 'onHide', function(){ return false; }) // stop the auto-closing by FUI
	  .modal('show'); // finally show the modal
    

}
p {
  padding: 10px;
}

.modalContent {
  border: 1px solid lime;
  margin: 5px;
  padding: 5px;
}

.modalHeading {
  border: 1px solid cyan;
  margin: 5px;
  padding: 5px;
}

.modalBody {
  border: 1px solid magenta;
  margin: 5px;
  padding: 5px;
}

.modalContent {
  background-color: white;
}

.ipt {
  margin: 5px 20px;
  display: block;
}
<link href="https://fomantic-ui.com/dist/semantic.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://fomantic-ui.com/dist/semantic.js"></script>

<body>
<p>Click the 'show modal' button to open a modal, then the 'Close' button to close it. See console for messages. The critical point is the final display of the modal artefact count which appears after a 2 second delay, allowing for transitions to complete. We want a zero - what will it be?
</p>

<p>
  <button id='b1'>Show a modal</button> <span>Count of DOM artifacts after close should be zero - value is >>>>> </span><span id='info'>[value will appear here after modal close]</span>
</p>

<div id='modalTemplate' style='display: none;'>
  <div class='modalContent'>
    <div class='modalHeading'>
       I am the heading
    </div>
    <div class='modalBody'>
      I am the body
    </div>
    
    <div class='modalButtons'>
    </div>
    
  </div>
</div>

</body>

【问题讨论】:

    标签: semantic-ui fomantic-ui


    【解决方案1】:

    答案是使用 当前 modal('destroy') 和 modal('remove') 结束动画完成后的未记录功能。

    .modal('setting', 'onVisible', function(){
      ele
        .on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
         function(e){
            console.log('Animation complete')
            $(this).off(e);    // remove this listener
            $(this).modal('destroy');  // take down the modal object
            $(this).remove();    // remove the modal element, at last.
         });
      })
    

    如果您没有观察到关闭过渡的完成,则 FUI 会抛出有关缺少元素的过渡的警告。

    Modal.Destroy 清除 FUI 附加到 JQuery 模态元素的模态对象。 ele.remove() 是standard JQuery remove function。结果是,根据我的要求,先前制作的模态元素已从 DOM 中删除。

    有一个人工制品,即 FUI dimmer div,但我迄今为止的测试表明这不是问题,这意味着它们不可见并且不会随着时间的推移而堆积。 p>

    请参阅下面的 sn-p 以获取工作示例。解决方法请看 JS 部分末尾。

    var fnSpecial = function(){
    	console.log('Close button click function - return true to hide');
      // ... do function activity here....
      return true;
    }
    
    $('#b1').on('click', function(){
    	
      makeModal({
      	title: 'I be modal',
        content: 'Modal be I !',
        actions: [
          { text: 'Close', fn: fnSpecial}, // for more buttons in the modal add more entries here. 
        ]    
      })
    
    })
    
    
    
    function makeModal(opts){
      // create your modal element - I grab the modal template
      var tplt = $('#modalTemplate').html();
    
      // defaults for modal create
      var obj = {
        title: 'No title !',
        content: 'No content',
        actions: [
        ]
      }
    
      // Merge the above defaults with the user-supplied options
      obj = $.extend(obj, opts);
    
      // Apply modal options to the soon-to-be modal element 
      var ele = $(tplt);
      ele.find('.modalHeading').html(obj.title);
      ele.find('.modalBody').html(obj.content);
      ele.addClass('modalContentCopy');
    
    	var modalButtons = ele.find('.modalButtons');
    	for (var i =0, max = obj.actions.length; i < max; i = i + 1 ){
      
      	var btn = $('<button >' + obj.actions[i].text + '</button>');
        var fn = obj.actions[i].fn;
        btn.data('fn', fn); // store the callback on the element to avoid closures.
        
        btn.appendTo(modalButtons);
        
        btn.on('click', function(e){    
        	var fn = $(this).data('fn');
          
          if (typeof fn === "function"){
          
            var hide = fn(); // IMPORTANT: the function triggered for the button must return true to close the modal or false to keep it open !
    
            console.log('Button says hide=' + hide)
    
            if (hide){
    
                ele.modal('destroy');
                ele.modal('hide');
    
                  $('#info')
                    .html('***');
                    
                // wait 2 secs and see if the DOM element has gone
                setTimeout( function(){
                  var num = $('#theBody').find('.modalContentCopy').length;
                  $('#info')
                    .html(num)
                    .css({ backgroundColor: (num === 0 ? 'lime' : 'red')});
                  }, 2000);
            }
          }
          
        });  
      }
    
     
    	// Simple example of how to reveal the modal element as a f-ui modal 
      ele
        .appendTo($('body'))
    
        .modal('setting', 'transition', "vertical flip")
        .modal('setting', 'onHide', function(){ return false; }) // stop any button closing the modal
    
        // <solution starts>
        .modal('setting', 'onVisible', function(){
          ele
            .on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
             function(e){
                console.log('Animation complete')
                $(this).off(e);
                $(this).modal('destroy');
                $(this).remove();
             });
          })
        // <solution ends>
        
    	  .modal('show'); // finally show the modal
        
    
    
     
    
    }
    p {
      padding: 10px;
    }
    
    .modalContent {
      border: 1px solid lime;
      margin: 5px;
      padding: 5px;
    }
    
    .modalHeading {
      border: 1px solid cyan;
      margin: 5px;
      padding: 5px;
    }
    
    .modalBody {
      border: 1px solid magenta;
      margin: 5px;
      padding: 5px;
    }
    
    .modalContent {
      background-color: white;
    }
    
    .ipt {
      margin: 5px 20px;
      display: block;
    }
    <link href="https://fomantic-ui.com/dist/semantic.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://fomantic-ui.com/dist/semantic.js"></script>
    
    <body id='theBody'>
    <p>Click the 'show modal' button to open a modal, then the 'Close' button to close it. See console for messages. The critical point is the final display of the modal artefact count which appears after a 2 second delay, allowing for transitions to complete. We want a zero - what will it be?
    </p>
    
    <p>
      <button id='b1'>Show a modal</button> <span>Count of DOM artifacts after close should be zero - value is >>>>> </span><span id='info'>[value will appear here after modal close]</span>
    </p>
    
    <div id='modalTemplate' style='display: none;'>
      <div class='modalContent'>
        <div class='modalHeading'>
           I am the heading
        </div>
        <div class='modalBody'>
          I am the body
        </div>
        
        <div class='modalButtons'>
        </div>
        
      </div>
    </div>
    
    </body>

    【讨论】:

      猜你喜欢
      • 2012-12-13
      • 1970-01-01
      • 2011-10-24
      • 2022-12-31
      • 2012-10-17
      • 2012-04-25
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      相关资源
      最近更新 更多