在没有克隆/复制的多个位置显示DOM节点

时间:2012-03-31 02:59:25

标签: javascript html css

声明:

我在这里过分善待,试图提供足够的背景来预先解决你们所有人可能对我提出的问题。不要害怕这个问题的长度:我所写的大部分内容都是非常可以浏览(特别是我提出的潜在解决方案)。

目标:

我希望实现的效果是在同一页面的多个位置显示相同的元素(和所有后代)。我当前的解决方案(请参阅下面的更多详细信息)涉及必须克隆/复制,然后追加到我希望它出现在DOM中的所有其他位置。我在这里要求的是更好(更有效)的解决方案。我对可能更有效的解决方案有一些想法(见下文)。请判断/批评/解散/补充这些,或者添加您自己更优秀的解决方案!

"为什么"你问?

嗯,我想要多次显示的元素(以及它的后代)可能具有很多属性和内容 - 所以克隆它,并将其附加到其他地方(有时不止一个)其他地方)可以成为一个资源占用的DOM操作操作。

某些背景信息:

我无法准确描述这种情况(该死的NDA')但基本上我所获得的是一个WYSIWYG html文档编辑器。当一个人正在编辑DOM时,我实际上正在保存"原始"节点和"改变了#34;节点通过将它们包装在div中,隐藏"原始"并让用户将新的("已更改的")节点修改为他们心中的内容。这样,用户可以在保存之前轻松查看他们所做的更改。

之前,我只是让用户浏览" diff divs"并暂时取消隐藏"原始"节点,以显示更改"内联"。我现在要做的就是让用户看到整个"原创"文档及其编辑("已更改的")文档并排查看。而且,我可能希望通过多个编辑会话保存更改,并显示“N' N'同时并排版本的数量。

当前解决方案:

我目前解决此问题的方法如下:

将整个dang dom(好吧,除了"工具栏"以及他们实际上并没有实际编辑的东西)包含在div中(我打电话给" pane1&# 34;),并创建一个新的div(我将调用" pane2")。然后将pane1的内容深度克隆到pane2,并在pane1中仅显示"原始"节点,并在pane2中只显示"已更改"节点(在差异区域中 - 其外的所有内容都将由工具栏中的切换开关显示/隐藏)。然后,对窗格3到N进行重复。

当前解决方案的问题:

如果用户正在编辑的文档变得超长,或包含图片/视频(具有不同的src属性)或包含许多花哨的样式事物(列,表等),那么DOM可能会变得非常大/复杂并试图克隆和操纵它可以使浏览器慢慢爬行或死亡(取决于DOM的大小/复杂性以及需要制作多少克隆以及浏览器/机器的效率& #39; s正在运行)。如果大小是问题,我当然可以做一些事情,比如从DOM中删除隐藏的节点,但是更多的DOM操作操作会占用资源。

潜在解决方案:

1。找到一种方法使DOM更简单/轻量化

因此,我目前正在进行的克隆/操作更有效率。 (当然,我尽可能地尝试这样做,但也许我真的可以做到这一点。)

2。使用Canvas元素或其他东西创建版本的静态表示。

我听说有一个技巧可以将HTML包装在SVG元素中,然后将其用作图像源并将其绘制到画布上。我认为那些静态画布(canvi?)的内存占用量比克隆的DOM节点要小得多。并且操纵DOM(隐藏/显示适当的节点),然后绘制图像(冲洗和重复)应该更快和更好。比克隆节点和操纵克隆更有效。 (也许我错了?请告诉我!)

我已经在有限的容量中尝试了这一点,但是将我的HTML包装在SVG中的方式与它在几个奇怪的情况下呈现的方式相混淆 - 也许我只需要稍微传达元素来获取他们要正确显示。

3。找一些神奇的元素

只是引用另一个节点并且看起来像它一样,而不是一个真正的克隆(因此在某种程度上神奇地更加轻量级)。即使这意味着我也无法将这个神奇的元素与节点分开操作,它会引用" (或其假孩子) - 在这种情况下,我仍然可以将此用于未更改的部分,并希望减少一些内存使用/ DOM操作操作。

4。在服务器端执行一些步骤。

我确实能够执行服务器端代码,因此可能会更高效(我的一些用户可能在移动设备或旧设备上)以获得所有ajax-y并发送DOM的相关部分(可能是用户正在编辑的文档的" root"或者只是特别重的" diff divs")到要克隆/操作的服务器,然后请求服务器操作的"克隆"并坚持在适当的窗格/地方。

5。假装它使它感觉到#34;更有效率

我不是一次性完成这些操作,而是让浏览器等到操作完成后重新绘制UI,我可以在" chunks"中进行操作。然后让浏览器重新渲染并在进行下一个块之前休息一下。这可能实际上会花费更多的时间,但对于临时用户来说,它可能会感觉到#34;更快(哈哈,傻瓜......)。最后,我想,用户体验是最重要的。

脚注:

同样,我是NDA,这使我无法在此处发布实际代码,就像我一样。我认为我已经彻底解释了这种情况(可能太彻底 - 如果存在这样的事情)所以你不必看到代码给我一个通用的答案。如果需要,我想我可以编写一些示例代码,这些代码与我公司的IP有很大不同,并在此处发布。如果您愿意我这样做,请告诉我,我很乐意帮忙(好吧,不是真的,但无论如何我都会这样做)。

5 个答案:

答案 0 :(得分:6)

看看CSS background elements。它们允许您在别处/重复显示DOM节点。它们当然是只读的,但应该直播。

你可能仍然需要围绕它们提出很多魔法,但它是一个类似的解决方案:

  
      
  1. 使用Canvas元素或其他东西创建版本的静态表示。
  2.   

CSS背景元素也非常具有实验性,因此如果您必须支持一系列浏览器,那么您可能无法使用它们。

答案 1 :(得分:3)

老实说,在读完这个问题之后,我几乎认为它属于“过于苛刻的篮子”,但经过一番思考后,或许我有一些想法。

这是一个非常困难的问题,我越是想到它越多我意识到没有真正的方法可以逃脱需要克隆。你是对的,你可以创建一个SVG或Canvas,但它看起来不一样,虽然付出了相当大的努力,我相信你可以非常接近,但不确定它的效率。您可以渲染HTML服务器端,拍摄快照并将图像发送到客户端,但这绝对不可扩展。

我能想到的唯一建议如下,抱歉,如果他们啰嗦:

  • 你是如何做这个克隆的?如果您正在浏览每个元素,并且当您浏览每个元素时,您正在创建一个克隆并逐个复制属性,那么这就是heaavvvyy。我强烈建议使用jQuery clone,因为我的猜测是它比你的解决方案更有效。此外,当您进行结构更改时,利用jQuery的detach / remove(本机JS:removeChild())方法可能会很有用,因为这会将元素从DOM中取出,因此您可以在重新插入之前对其进行更改。
  • 我不确定你是如何得到你的所见即所得,但是因为它们很重要而避免使用输入。如果你必须那么我假设他们看起来不像输入所以只需将它们换成另一个元素和样式(CSS)来匹配。在将克隆重新插入DOM之前,请确保执行这些交换。
  • 在显示用户比较时,不要直接放置视频。我们要做的最后一件事是将第三方对象注入页面。使用图像,您只需在比较时执行此操作。再次,在将克隆插入DOM之前进行交换。
  • 我假设克隆的元素不会附加javascript(如果有,那么删除它,较少的移动部件更有效率)。但是,“已更改”元素可能会附加一些JS事件,因此可能会在比较期间删除它们。
  • 使用Chrome / FF重绘/重排工具查看重构DOM时页面的工作方式。这很重要,因为你可能会做一些“令人敬畏”的动画,这会耗费你很多资源。请参阅http://paulirish.com/2011/viewing-chromes-paint-cycle/
  • 尽可能使用CSS而不是内联样式,因为现代浏览器已经过优化以处理CSS文档
  • 你能做到这一点,以便你的用户使用像Chrome这样的快速现代浏览器吗?如果它是内部的那么可能是值得的。
  • 您可以在Silverlight或Adobe Air中执行这些操作吗?这些对象获得特殊的资源权限,因此这很可能会解决您的问题(根据我想象的问题的深度)
  • 这个有点左边的字段,但你可以在另一个窗口打开吗?像Chrome这样的现代浏览器会在自己的流程中运行另一个窗口,这可能有所帮助。

毫无疑问,你可能比我更关注这些事情,但祝你好运。很好奇你是如何解决它的。

答案 2 :(得分:2)

您也可以尝试:http://html2canvas.hertzen.com/
如果它适用于你,画布有更好的支持。

答案 3 :(得分:1)

为了获得您的“并排”原始文档和修改过的文档..而不是将所有pane1克隆到pane2 ..您是否只需将原始文档加载到正在编辑的内容旁边的iframe中?不那么笨重?

您可以调整文档在iframe中的显示方式(例如隐藏可编辑内容之外的内容)。

也许当您“保存”更改时,请将更改写入文件(或临时文件)并在新的iframe中打开它?这可能会完成你的“多个编辑会话”......有多个iframe以各种状态显示文档。

大声思考......

(如果我遗失/误解了您的任何目标/要求,请提前抱歉)

答案 4 :(得分:0)

我不知道你的情况是否已经如此,但你应该考虑使用jQuery库,因为它允许执行不同类型的DOM元素操作,例如创建内容并一次将其插入到多个元素中或选择一个元素页面并将其插入另一个页面。

查看.appendTo(),. html(),. text(),. addClass(),. css(),. attr(),. clone()

http://api.jquery.com/category/manipulation/

很抱歉,如果我只是指出你已经知道甚至可以使用的东西,但是你的NDA会更准确地回答。