嗨,我想在 dom 之外进行 dom 选择和操作。
目标是从 dom 构建我的小部件,并仅在准备好后将其插入 dom。
我的问题是文档片段不支持 getElementById。我也尝试过 createElement 和 cloneNode,但它也不起作用。
我正在尝试用普通的js来做到这一点。我习惯用 jQuery 来做这件事,它可以很好地处理它。我试图在 jQuery 源代码中找到诀窍,但到目前为止没有成功......
奥利维尔
嗨,我想在 dom 之外进行 dom 选择和操作。
目标是从 dom 构建我的小部件,并仅在准备好后将其插入 dom。
我的问题是文档片段不支持 getElementById。我也尝试过 createElement 和 cloneNode,但它也不起作用。
我正在尝试用普通的js来做到这一点。我习惯用 jQuery 来做这件事,它可以很好地处理它。我试图在 jQuery 源代码中找到诀窍,但到目前为止没有成功......
奥利维尔
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 功能。假设您有能力安装另一个库。
希望这可以帮助!
我做过类似的事情,但不确定它是否能满足您的需求。创建一个“保持区域”,例如平原<span id="spanReserve"></span>
或<td id="cellReserve"></td>
. 然后你可以在 JS 函数中做这样的事情:
var holdingArea = document.getElementById('spanReserve');
holdingArea.innerHTML = widgetHTMLValue;
编辑:
沿着这些线简单的东西怎么样:
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 或其他开源库中的所有工作更慢。
哦,还有……我认为(猜测)jQ 的诀窍是元素不在 DOM 之外。我可能是错的,但我认为当您执行以下操作时:
$('<div></div>');
它实际上在 DOM 文档中只是不是主体/头节点的一部分。不过,这可能是完全错误的,这只是一个猜测。
所以你让我很好奇哈哈。我看了看 sizzle.. 答案是 - 它不使用 DOM 方法。似乎使用一种算法来比较映射到选择器类型的各种 DOMNode 属性 - 除非我错过了一些东西......这是完全可能的:-)
然而,正如下面在评论中指出的那样,Sizzle 似乎不适用于 DocumentFragments ......所以回到第一方:-)
现代浏览器(阅读:不是 IE)在 Element API 中有querySelector方法。您可以使用它在 DocumentFragment 中按 id 获取和元素。
jQuery 使用sizzle.js
它在 DocumentFragments 上的作用是:深入循环片段中的所有元素,检查元素的属性(在您的情况下为 'id' )是否是您要查找的属性。据我所知,sizzle.js 也使用 querySelector(如果可用)来加快速度。
如果您正在寻找跨浏览器兼容性,您可能正在寻找,您将需要编写自己的方法,或检查 querySelector 方法。
您确实有两个工具可以使用,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()
方法。
听起来你正在做正确的事情。不知道为什么它不工作。
// 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)