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


免责声明:

我试图提供足够的背景来预先解决你们所有人可能对我提出的问题。不要被这个问题的长度吓到:我写的很多东西都是 非常 可以浏览(特别是我提出的潜在解决方案)。

目标:

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

“为什么?”你问?

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

一些背景:

我无法准确描述这种情况(该死的NDA!)但是 实质上 我得到的是一个WYSIWYG html文档编辑器。当一个人正在编辑DOM时,我实际上是将“原始”节点和“已更改”节点保存在div中,隐藏“原始”并让用户修改新的(“已更改”)节点他们心中的内容。这样,用户可以在保存之前轻松查看他们所做的更改。

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

当前解决方案

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

将整个dang dom(除了“工具栏”以及它们实际上没有编辑的东西)包装在一个div(我称之为“pane1”)中,并创建一个新的div(我称之为“pane2”) “)。然后将pane1的内容深度克隆到pane2中,并在pane1中仅显示“原始”节点,并且在pane2中仅显示“已更改”的节点(在差异区域中 - 除此之外的所有内容都将由切换开关显示/隐藏工具栏)。然后,对窗格3到N重复此操作。

当前解决方案的问题:

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

潜在解决方案

1.找到一种方法使DOM更简单/轻量级

所以我目前正在进行的克隆/操作更有效率。 (当然,我正尽力做到这一点 无论如何,但也许这就是我所能做的一切)。

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

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

我在有限的容量中尝试过这种方法,但是在SVG中将我的HTML包含在一些奇怪的情况下呈现它的方式 - 也许我只需要对元素进行一些消息以使它们正确显示。

3.找一些神奇的元素

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

4.执行服务器端的某些步骤。

我确实有能力执行服务器端代码,所以可能效率更高(我的一些用户 威力 在移动设备或旧设备上)获取所有ajax-y并发送DOM的相关部分(可能是用户正在编辑的文档的“根”,或者只是特别重的“diff divs”)到服务器是克隆/操纵,然后请求服务器操作的“克隆”并将它们粘贴在适当的窗格/位置。

假它使它“感觉”更有效率

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

脚注:

再一次,我是NDA'd,这阻止我在这里发布实际代码,就像我想的那样。一世 认为 我已经彻底解释了这种情况(也许吧 太彻底了  - 如果存在这样的事情)所以你不必看到代码给我一个通用答案。如果需要,我想我可以编写一些示例代码,这些代码与我公司的IP有很大的不同,并在此处发布。如果你想让我这样做,让我知道,我会很乐意(好吧,不是真的,但无论如何我都会这样做)。

提前感谢您的任何建议!


12247
2018-03-31 02:59


起源

对不起,但......什么? - Matt Ball
1投票给4号阿贾克斯 - Dave Thomas
@MДΓΓБДLL - 对不起,但是“对不起,但......什么?”什么? - JKing
这是一篇论文还是什么?你至少可以归结为冰山一角吗? - Joseph
我实际上读了整个该死的东西! = P - Tivie


答案:


看一眼 CSS背景元素。它们允许您在其他地方/重复显示DOM节点。它们当然是只读的,但应该更新。

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

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

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


6
2018-04-11 14:07



使用这些功能可能有点早。 - Chaos
@Chaos幸运的是,使用前沿的东西是一种加分,但如果没有人能够真正使用它,肯定不会。看来文章声称目前只有firefox使用它,是过时还是真的?我会在工作中测试它mañana。说实话,我是 最 在性能方面关注“移动”设备。我追求的大多数桌面环境应该能够管理 - 除非DOM变得非常庞大。 - JKing
因此,为了记录,我接受这个答案'因为它是我真正想要的(我知道我以前听说过这个,但是再也找不到了,所以谢谢!)但是我给了Chaos赏金,因为它似乎更多地考虑了它的答案。 - JKing
我实际上错过了有关移动设备的部分!能够在移动设备中为用户提供所有这些功能非常具有挑战性。太难了篮子!考虑到你的兼容性限制,我会抛弃CSS背景元素,因为它只适用于FF(可能不是FF的移动版本),FF移动目前只适用于Android。 Silverlight将在Windows Phone 7中运行,但谁拥有其中一个?顺便说一句,谢谢JKing,这是一个发人深省的问题。 - Chaos
唉,我的赏金被掠夺了! :P - Jacob Swartwood


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

这是一个非常棘手的问题,我越是想到它就越能意识到没有真正的方法可以逃脱需要克隆。你是对的,你可以创建一个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等现代浏览器会在自己的流程中运行其他窗口,这可能有所帮助。

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


3
2018-04-11 14:08



好吧,我 试 为了给你赏金,但显然我要等几个小时......我很好奇空气/银光会如何帮助,但是我觉得很累,因为据我所知,插件在移动设备上并不是那么可靠。当我有更多机会探索各种选项时,我会告诉您哪些/哪种组合我发现最好。 - JKing
还有太硬的篮子吗?因为这听起来很神奇! - JKing
感谢JKing的观点 - Chaos


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


2
2018-04-13 10:32





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

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

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

只是大声思考......

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


1
2018-04-12 05:22



Nonono,你似乎做得很好......所以,你所说的是加载到iframe比将节点克隆到同一文档中要小得多?我很熟悉从框架外部修改iframe内容,所以如果它确实在某种程度上更有效,它可能是一个可行的解决方案......你是在谈论再次查询服务器的iframe内容,还是只是传递HTML字符串或者客户端上的json还是空的iframe? - JKing
我愿意给你们所有人一点点赏金!我可以开始一个新的赏金并将其奖励给现有的答案吗? - JKing
具体来说,我的意思是将iframe的源设置为正在编辑的文档。我不确定它是否会更高/更低效,但我想象它会归结为iframe中的文档/内容的加载时间(仅一个dom元素)与未知数量的DOM进行操作(相乘)由'n'并排版本)。无论如何,我不是一个iframe人,只是头脑风暴。 - brains911
很好的想法,但我在一次会议中与铬狂热者进行的对话(是的,不是非常官方),iframe在同一过程中运行。如果这是真的(我似乎无法找到对它的引用来支持它),它只会降低效率,因为您所做的只是添加更多资源。 - Chaos


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

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

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

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


0
2018-03-31 03:23



我认为JKing希望避免克隆。这就是问题的关键。 ;-) - Greg Pettit
是的,jQuery很好,但它只会让我的任务更容易,而不是运行它的计算机 - 这就是我所追求的。不过谢谢! - JKing