【问题标题】:Is there any way to find an element in a documentFragment?有没有办法在 documentFragment 中找到一个元素?
【发布时间】:2010-12-11 05:31:28
【问题描述】:
var oFra = document.createDocumentFragment();
// oFra.[add elements];
document.createElement("div").id="myId";
oFra.getElementById("myId"); //not in FF

如何在将片段附加到文档之前获取“myId”?

【问题讨论】:

  • 这个问题是在 2009 年提出的。在 2012 年,我们有 querySelectorAll,它适用于文档片段。请参阅下面@Stephen 的回答。

标签: javascript dom documentfragment


【解决方案1】:

怎么样:

var oFra = document.createDocumentFragment();
var myDiv = document.createElement("div");
myDiv.id="myId";
oFra.appendChild(myDiv);
oFra.getElementById("myId"); //not in FF

除非您已将创建的 div 添加到您的文档片段中,否则我不确定为什么 getElementById 会找到它?

--编辑

如果您愿意推出自己的 getElementById 函数,那么您应该能够获得所需的引用,因为此代码有效:

var oFra = document.createDocumentFragment();
var myDiv = document.createElement("div");
myDiv.id = "myId";
oFra.appendChild(myDiv);
if (oFra.hasChildNodes()) {
    var i=0;
    var myEl;
    var children = oFra.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (children[i].id == "myId") {
            myEl = children[i];
        }
    }
}
window.alert(myEl.id);

【讨论】:

  • 我试图避免这种解决方案,因为我在片段中设计了一个数据输入表单,添加事件并附加到文档。在 IE 中工作。原因似乎是在 IE 片段中继承自文档,但在 FF 中继承自 Node (W3C)
  • 好的,但是如果您仍然在 JS 中构建表单,为什么不在创建元素时保留对元素的引用并使用这些引用来添加事件?
  • 每个表单都有很多按钮、文本框、组合等。我尝试坚持使用 id 并尽可能减少 dom 对象引用。我将先附加并稍后分配事件。
  • 我一定遗漏了一些关于你正在做的事情 - 你如何创建元素并将它们附加到你的文档片段而不创建对它们的引用?权衡是在创建元素时存储对元素的引用,而不是立即将其丢弃,而不是在几毫秒后扫描整个文档以重新创建对该元素的引用。
  • IE 的createDocumentFragment 实际上并没有创建DocumentFragment,而是创建了Document: msdn.microsoft.com/en-us/library/ms536387(VS.85).aspx(我喜欢他们说“这是在DOM Level 1 中定义的”的方式,没有解释他们实际上并没有在 HTML 中实现 DocumentFragment,因此该方法返回了错误类型的对象...)
【解决方案2】:

没有。 DocumentFragment API 至少可以说是最小的:它没有定义属性或方法,这意味着它只支持Node API 中定义的属性和方法。由于getElementById 等方法是在Document API 中定义的,因此它们不能与DocumentFragment 一起使用。

【讨论】:

  • 即使在 Document API 中定义了 getElementById,它也不会对未附加到 dom 的新创建元素起作用。 myObj.getElementById 不起作用,而 myObj.getElementsByTagName 起作用。
  • @Olivvv:这是意料之中的:getElementByIdHTMLDocument w3.org/TR/REC-DOM-Level-1/level-one-html.html#ID-36113835 的方法,而 getElementsByTagNameDocument w3.org/TR/REC-DOM-Level-1/level-one-core.html#i-DocumentElement @ 的方法987654326@ 因此,当尝试在 Element 类型的对象上调用它时,getElementById 总是会抛出异常,无论该元素是否附加到 DOM。
【解决方案3】:

下面列出的外部源显示了以下代码 sn-p:

var textblock=document.createElement("p")
textblock.setAttribute("id", "george")
textblock.setAttribute("align", "center")

其中显示了设置对象 ID 参数的不同方式。

Javascript Kit - Document Object Methods

【讨论】:

    【解决方案4】:

    NickFitz 是对的,DocumentFragment 在标准或浏览器中没有您期望从 DocumentElement 获得的 API(这很遗憾;能够设置片段的innerHTML

    即使是框架在这里也帮不了你,因为它们往往要求节点在文档中,或者在上下文节点上使用片段上不存在的方法。您可能必须自己编写,例如:

     function Node_getElementById(node, id) {
          for (var i= 0; i<node.childNodes.length; i++) {
              var child= node.childNodes[i];
              if (child.nodeType!==1) // ELEMENT_NODE
                  continue;
              if (child.id===id)
                  return child;
              child= Node_getElementById(child, id);
              if (child!==null)
                  return child;
          }
          return null;
     }
    

    几乎可以肯定的是,在进行过程中跟踪引用比依赖像上面这样幼稚、性能不佳的函数要好。

    var frag= document.createDocumentFragment();
    var mydiv= document.createElement("div");
    mydiv.id= 'myId';
    frag.appendChild(mydiv);
    // keep reference to mydiv
    

    【讨论】:

      【解决方案5】:

      所有这些答案都相当陈旧,早在querySelectorAllquerySelector 还没有被广泛使用的时候。应该注意的是,这两个接受 CSS 选择器作为参数的函数在现代浏览器中确实适用于 DocumentFragments,并且应该是处理问题中情况的首选方式。一些答案中提出的替代解决方案对于不支持querySelectorAllquerySelector 的旧版浏览器来说是一个很好的方法。

      这是一个示例用法:

      var df = document.createDocumentFragment();
      var div = document.createElement('div');
      div.id = 'foo';
      df.appendChild(div);
      var result = df.querySelector('#foo'); // result contains the div element
      

      一个好的实现应该首先使用对象检测来查看浏览器是否支持这一点。例如:

      function getElementByIdInFragment(fragment, id) {
          if (fragment.querySelector) {
              return fragment.querySelector('#' + id);
          } else {
              // your custom implementation here
          }
      }
      

      【讨论】:

      • 我确信除了从文档片段中取回元素之外,还有其他方法。无论如何你将失去所有的好处
      【解决方案6】:

      使用 jQuery:

      // Create DocumentFragment
      var fragment  = document.createDocumentFragment(),
          container = document.createElement('div');
      
      container.textContent = 'A div full of text!';
      container.setAttribute('id', 'my-div-1');
      container.setAttribute('class', 'a-div-class');
      fragment.appendChild(container);
      
      // Query container's class when given ID
      var div = $('<div></div>').html(fragment);
      console.log(div.find('#my-div-1').attr('class'));
      

      jsFiddle:http://jsfiddle.net/CCkFs/

      不过,您有使用 jQuery 创建 div 的开销。有点hacky,但它有效。

      【讨论】:

      • $("
        ").find(#my-div-1 ") 有效。您只是无法搜索根节点。
      【解决方案7】:

      我的 DOM 在元素标签下有一个 #document-fragment

      这就是我正在使用的(使用 jQuery),还有一个用例,我在字符串中包含 HTML DOM -

       var texttemplate = $(filecontents).find('template').html();
      
      
       $(texttemplate).children()
      
            <p>​Super produced One​</p>​, 
            <appler-one>​</appler-one>, 
            <p>​Super produced Two​</p>, 
            <appler-two>​…​</appler-two>]
      
      $(texttemplate).html()
      
                      "<p>Super produced One</p>
                      <appler-one></appler-one>
                      <p>Super produced Two</p>
                      <appler-two>
                          <p>Super produced Three</p>
                          <appler-three></appler-three>
                      </appler-two>"
      
      
      $(texttemplate).find("appler-one")
      
                    [<appler-one>​</appler-one>​]
      

      【讨论】:

        【解决方案8】:

        到目前为止,找出你可以用 DocumentFragment 做什么和不能做什么的最好方法是检查它的原型:

        const newFrag = document.createDocumentFragment();  
        const protNewFrag = Object.getPrototypeOf( newFrag );
        console.log( '£ protNewFrag:' ); 
        console.log( protNewFrag ); 
        

        我明白了

        DocumentFragmentPrototype { getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), prepend: prepend(), append: append(), children: Getter, firstElementChild:Getter,lastElementChild:Getter, childElementCount:Getter,还有 1 个……}

        ...这告诉我我可以做以下事情:

        const firstChild = newFrag.children[ 0 ];
        

        PS 这行不通:

        const firstChild = Object.getPrototypeOf( newFrag ).children[ 0 ];
        

        ...你会被告知“该对象没有实现 DocumentFragment 接口”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-17
          • 2023-03-22
          • 2015-04-22
          • 1970-01-01
          • 2020-05-05
          • 1970-01-01
          • 2018-10-08
          • 1970-01-01
          相关资源
          最近更新 更多