在节元素完成加载后捕获事件

Posted

技术标签:

【中文标题】在节元素完成加载后捕获事件【英文标题】:Capture the event after a section element has finished loading 【发布时间】:2015-11-30 10:48:14 【问题描述】:

我有一个包含部分的 div:

<div class="Placeafterthis">
</div>
...
<div class="k-content">
<section class="rbs-section" id="id1" name="">
.. // section content
</section>
<section class="rbs-section" id="id2" name="">
.. // section content
</section>
<section class="rbs-section" id="id3" name="">
.. // section content
</section>
</div>

现在基本上这些部分是在 DOM 准备好时加载的。有没有办法可以检查特定部分何时完成加载?完成加载后,我需要克隆该部分并将其放在“Placeafterthis”div 之后。关于如何实现这一目标的任何建议?

【问题讨论】:

如何将内容绑定到这些 div?您是否使用了一些 ajax 调用,角度? 我没有做绑定。那已经完成了。我只是想获得该部分的就绪或加载事件。 部分、图像、iframe 中的内容类型是什么? 部分如何加载?向我们展示一些 js 魔法来帮助找到答案 部分中的内容只是按钮和网格列表控件,它们是通过 Kendo UI 加载的。网格列表:demos.telerik.com/kendo-ui/grid/index 【参考方案1】:

您可以使用MutationObserver 来检测何时将节点添加到.k-content,使用jQuery 将clone 添加到它们之后,并将它们附加到.Placeafterthis 之后(demo):

var kContent = $('.k-content'); // the original container in which the items will be placed
var $Placeafterthis = $('.Placeafterthis'); // the cloned elements target marker placeholder

function mutationHandler(mutation)  // the mutation handler will deal with the addition of new nodes to the original container
    var addedNodes = mutation.addedNodes;

    if (!addedNodes.length)  // if no added nodes return
        return;
    

    $.each(addedNodes, function ()  // iterate the add nodes
        var $element = $(this);

        if (!$element.hasClass('rbs-section'))  // if the node doesn't have the right class continue to the next one
            return true;
        

        var $prevSections = $Placeafterthis.find('~ .rbs-section'); // find if there are already sections append to the target
        var $target = $prevSections.length === 0 ? $Placeafterthis : $prevSections.last(); // if there are sections take the last, if not use the marker

        /** note that using .clone(true) will also clone all jQuery event handlers and data from the original element. If you don't need this behavior, just use .clone() **/

        $target.after($element.clone(true)); // append after the target
    );


var observer = new MutationObserver(function (mutations)  // create a new mutation observer
    mutations.forEach(mutationHandler);
);

var config =  // config should include only childList because we just want added nodes 
    childList: true
;

observer.observe(kContent.get(0), config); // watch the original container with the observer

【讨论】:

似乎克隆withDataAndEvents的唯一答案 想一想,我不确定这是所要求的行为。我将在代码中添加注释。【参考方案2】:

尝试使用 $.get() ,将响应附加到 .k-content ,在响应克隆时过滤选定 section 元素的 id ,将字符添加到 id 以防止 idDOM 中重复,在.Placeafterthis 之后插入;使用 jQuery 承诺对象定义 getSections 设置为 this ,递归调用 getSections 以在 sections 数组上返回 Array.prototype.shift() 以按顺序为索引 0 处的每个项目返回 $.get(),否则如果 false!! 运算符返回section[0] 返回this.promise()

    // `id`s of `section` elements to append to `.k-content`
    var sections = ["#id1", "#id2", "#id3"];
    // selected `id` to do stuff with
    var selected = sections[1];
    // container
    var container = $(".k-content");
    // `complete` handler for `$.get()` requests
    function selectedId(html, textStatus, jqxhr) 
        // decode `data` : `id` sent with request
        var id = decodeURIComponent(this.url.split("?")[1]).split("=")[1];
        // append `section` to `container`
        container.append($(html).filter(id));
        // if `selected` appended to `container` ,
        // and `selected` is not in `DOM` directly after `.Placeafterthis` element
        // clone `selected` , append after `.Placeafterthis` element
        if (container.find(selected).is("*") 
          && !$(".Placeafterthis + " + selected + "-a").is("*")) 
            var clone = $(selected, container).clone()
                        .attr("id", selected.slice(1) + "-a");
            $(".Placeafterthis").after(clone)
        
    

    var getSections = function getSections() 
        var p = sections.shift();
        return !!sections 
               && $.get("http://fiddle.jshell.net/guest271314/rvt8evoy/show/"
               , "id": p, selectedId).then(getSections)
    ;

    getSections()
    .then(function() 
      console.log("complete")
    )

jsfiddle http://jsfiddle.net/1d6vmdpt/5/

【讨论】:

【参考方案3】:

我从here 获得了克隆代码并根据需要进行了修改。在最后一个 script 标记上使用 async 总是对我有用,但是在外部脚本上使用它,我只是出于演示目的将其内联。最重要的是,脚本位于结束正文标记处,以避免阻塞。在 DOMContentLoaded 事件上附加了一个事件侦听器,这就是这些部分应该准备好的时候(除非这些部分中有 iframe...)。我为所有元素的边框上色以便于查看。

更新:在阅读了 guest271314 的帖子后,它提醒我我忽略了克隆的 ID。作为克隆,它们也有相同的 id,所以我对其进行了一些重构并添加了一些星球大战。

section[id^="id"] 
  border: 3px solid silver;
  width: 200px;
  height: 25px;

section[id^="st"] 
  border: 3px solid black;
  width: 200px;
  height: 25px;

.kamino-content 
  border: 3px dashed blue;
  width: 200px;
  height: 200px;

.Placeafterthis 
  border: 3px dotted orange;
  width: 200px;
  height: 75px;
<div class="Placeafterthis">
  Place After This
</div>

<div class="kamino-content">
  <section class="fett-dna" id="id1" name="jango">
    .. // section content
  </section>
  <section class="fett-dna" id="id2" name="jango">
    .. // section content
  </section>
  <section class="fett-dna" id="id3" name="jango">
    .. // section content
  </section>
  Kamino-Content
</div>



<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.4.min.js"></script>

<!-- You should really do this: <script async src="external.js"></script> -->

<script async>
  document.addEventListener("DOMContentLoaded", cloneLab, false);

  function cloneLab() 
    var vat = $('.kamino-content'),
      squad = $('.fett-dna').size(),
      fett = vat.find('.fett-dna');
    fett.each(function(idx, val) 
      var trooper = $(this).clone();
      trooper.attr("id", "st" + (squad + idx)).attr("name", "stormtrooper");
      trooper.insertAfter('.Placeafterthis');
    );
  
</script>

【讨论】:

【参考方案4】:

如果您将脚本放在最后一部分之后:

<section class="rbs-section" id="id3" name="">
.. // section content
</section>

<script>
  (function() 
    var s3 = document.getElementById("id3");
    ...
  )();
</script>

那么它将在该元素之后被调用,其前身将出现在 DOM 中。

【讨论】:

以上是关于在节元素完成加载后捕获事件的主要内容,如果未能解决你的问题,请参考以下文章

捕获冒泡

JS的事件冒泡和事件捕获

事件处理模型——事件冒泡事件捕获

浅谈js的事件冒泡和事件捕获

浅谈js的事件冒泡和事件捕获

一个DOM元素绑定多个事件时,先执行冒泡还是捕获