4

嗨,我想在 dom 之外进行 dom 选择和操作。

目标是从 dom 构建我的小部件,并仅在准备好后将其插入 dom。

我的问题是文档片段不支持 getElementById。我也尝试过 createElement 和 cloneNode,但它也不起作用。

我正在尝试用普通的js来做到这一点。我习惯用 jQuery 来做这件事,它可以很好地处理它。我试图在 jQuery 源代码中找到诀窍,但到目前为止没有成功......

奥利维尔

4

6 回答 6

1

jQuery 将首先尝试使用getElementById,如果这不起作用,它将搜索所有使用的 DOM 元素,getAttribute("id")直到找到您需要的元素。

例如,如果您构建了以下未附加到的 DOM 结构document并将其分配给 javascript var widget

<div id="widget">
    <p><strong id="target">Hello</strong>, world!</p>
</div>

然后,您可以执行以下操作:

var target;

// Flatten all child elements in the div
all_elements = widget.getElementsByTagName("*");

for(i=0; i < all_elements.length; i++){
    if(all_widget_elements[i].getAttribute("id") === "target"){
        target = all_widget_elements[i];
        break;
    }
}

target.innerHTML = "Goodbye";

如果您需要的不仅仅是通过 ID 搜索,我建议安装 Sizzle 而不是复制 Sizzle 功能。假设您有能力安装另一个库。

希望这可以帮助!

于 2009-12-03T09:30:05.777 回答
1

我做过类似的事情,但不确定它是否能满足您的需求。创建一个“保持区域”,例如平原<span id="spanReserve"></span><td id="cellReserve"></td>. 然后你可以在 JS 函数中做这样的事情:

var holdingArea = document.getElementById('spanReserve'); holdingArea.innerHTML = widgetHTMLValue;

于 2009-12-02T14:14:24.623 回答
0

编辑:

沿着这些线简单的东西怎么样:

  DocumentFragment.prototype.getElementById = function(id) {
    for(n in this.childNodes){
      if(id == n.id){
        return n;
      }
    }

    return null;
  }

为什么不在您使用的任何其他库中使用 jQuery 或选择 API?AFAIK 所有主要库都支持片段选择。

如果你想跳过像 jQ/Prototype/Dojo/etc 这样的更大的库,那么你可以直接使用 Sizzle——它是支持 jQ 和 Dojo 的选择器引擎,它作为独立的提供。如果那也是不可能的,那么我想你可以潜入 Sizzle 源,看看发生了什么。总而言之,虽然看起来要付出很多努力来避免几十万,但你提出的代码在运行时会比 Sizzle 或其他开源库中的所有工作更慢。

http://sizzlejs.com/

哦,还有……我认为(猜测)jQ 的诀窍是元素不在 DOM 之外。我可能是错的,但我认为当您执行以下操作时:

$('<div></div>');

它实际上在 DOM 文档中只是不是主体/头节点的一部分。不过,这可能是完全错误的,这只是一个猜测。

所以你让我很好奇哈哈。我看了看 sizzle.. 答案是 - 它不使用 DOM 方法。似乎使用一种算法来比较映射到选择器类型的各种 DOMNode 属性 - 除非我错过了一些东西......这是完全可能的:-)

然而,正如下面在评论中指出的那样,Sizzle 似乎不适用于 DocumentFragments ......所以回到第一方:-)

于 2009-12-02T15:17:45.407 回答
0

现代浏览器(阅读:不是 IE)在 Element API 中有querySelector方法。您可以使用它在 DocumentFragment 中按 id 获取和元素。

jQuery 使用sizzle.js

它在 DocumentFragments 上的作用是:深入循环片段中的所有元素,检查元素的属性(在您的情况下为 'id' )是否是您要查找的属性。据我所知,sizzle.js 也使用 querySelector(如果可用)来加快速度。

如果您正在寻找跨浏览器兼容性,您可能正在寻找,您将需要编写自己的方法,或检查 querySelector 方法。

于 2009-12-03T16:35:01.407 回答
-1

您确实有两个工具可以使用,html() 和在 XML 文档上使用普通的 jQuery 操作运算符,然后将其插入 DOM。

要创建小部件,您可以使用html():

$('#target').html('<div><span>arbitrarily complex JS</span><input type="text" /></div>');

我认为这不是你想要的。因此,看看 jQuery 选择器的附加行为:当传递第二个参数时,它可以是它自己的 XML 片段,并且可以对这些文档进行操作。例如。

$('<div />').append('<span>').find('span').text('arbitrarily complex JS'). etc.

所有的操作符,如 append、appendTo、wrap 等都可以像这样处理片段,然后可以将它们插入到 DOM 中。

不过要注意一点:jQuery 使用浏览器的本机函数来操作它(据我所知),因此您在不同的浏览器上会得到不同的行为。确保格式良好的 XML。我什至让它拒绝了格式不正确的 HTML 片段。但是,最坏的情况是返回并使用字符串连接和html()方法。

于 2009-12-11T07:06:23.223 回答
-1

听起来你正在做正确的事情。不知道为什么它不工作。



// if it is an existing element
var node = document.getElementById("footer").cloneNode(true);

// or if it is a new element use
// document.createElement("div");

// Here you would do manipulation of the element, setAttribute, add children, etc.
node.childNodes[1].childNodes[1].setAttribute("style", "color:#F00; font-size:128px");

document.documentElement.appendChild(node)



于 2009-12-02T14:16:53.307 回答