我应该使用iframe而不是ajax吗?

10
我们正在构建一个Drupal网站,其中包含一个音频播放器,该播放器应在您浏览页面时保持播放(类似于soundcloud)。
目前,我们使用AJAX加载点击的标签,并将HTML注入页面并使用history.js操纵位置。
然而,存在一个主要缺点:
由于新加载的页面可能具有不同的CSS和JS,因此我们必须将当前脚本、样式和链接元素与AJAX响应文本进行比较(丑陋的regex),并仅添加尚未存在的新元素。通过这样做,加载另一页不会删除/删除/撤消一旦执行的脚本。这可能成为性能问题(而regex对标记本来就是)。
使用一个iframe可以解决这个问题和其他问题:
当您首次单击网站上的链接时,页面内容将被一个iframe替换,该框架只加载该页面。音频播放器位于原始DOM中,即iframe之外。单击iframe内部的链接也可以在历史记录API中捕获和使用。
因此,尽管我从来没有想过我会这么想:我认为在这里使用iframe可能是更好的选择,不是吗?
PS:我的主要问题是我无法控制网站上的不同页面具有不同的脚本,样式确实不是问题。如果只有一个巨大的静态JS和CSS网站范围内,我没有问题。
更新:除了在iOS中外,iframe解决方案运行良好。Iframe非常丑陋。尽管如此,我认为我们将使用iframe解决方案。

你可以有一个“reset.css”文件,它可以清除所有先前加载的CSS - 但是你需要知道每个页面将应用哪些CSS,这听起来像是你无法控制的。如果通过link加载CSS,则也可以卸载CSS,但同样取决于如何加载CSS,请在此处查看:https://dev59.com/z3I-5IYBdhLWcg3w8dYQ - freedomn-m
CSS没有问题。如果您删除样式或链接元素,则CSS将被撤消。如果您附加新的元素,则样式将得到更新。但是脚本的行为不同。 - Alex
为什么需要有不同的css/js文件?不能将它们连接/压缩并一次性提供服务吗?这样,在更改页面时,您只需要正确处理不同的状态(绑定事件、解除绑定...)。 - Luigi De Rosa
1
@luchaos 不是的,常见的 jQuery Ajax。 - Alex
“iframe” 真的是个很有问题的东西。我知道说起来容易做起来难,但如果你有不会相互冲突的脚本,而且只针对动态容器,那么完全可以避免使用它。 - ton
显示剩余3条评论
5个回答

3
我会说...保持简单原始。选择iframe解决方案,我知道这会摧毁你灵魂的一部分,但它是您问题的最简单解决方案,并且未来遇到问题的可能性最小。
KISS。

我们目前正在测试iframe方法,效果非常好。唯一的缺点是iOS系统,它在处理iframes时存在巨大问题和bug :( - Alex

3
我认为你可以使用iframe。在网站中嵌入页面使用iframe是可以的,这也是iframe的作用。
以前,iframe对SEO不利,但现在网络爬虫通常可以在你的网站和iframe内容之间移动。
使用iframe比使用“丑陋的正则表达式”更容易和简单。为什么不保持简单呢?KISS原则

如果您的目标是保持单个内容区域,那么这将起作用。 - CoveGeek
我们目前正在测试iframe方法,效果非常好。唯一的缺点是iOS系统,它在处理iframes时存在巨大问题和bug。我认为SEO不会成为一个问题,因为iframe只会在通过JS点击链接时生成。 - Alex

0

你可以尝试一些奇怪的东西。

首先,你可以将window对象与新对象进行比较,并删除所有额外的属性(这里有一个例子)。同样的事情也可以对documentHTMLElementArray.prototype对象和其他可能通过脚本扩展的对象进行操作。这样,你就可以消除大部分定义的内容,垃圾回收器会在某个时候丢弃它们。

其次,你需要删除所有事件监听器。这可以通过重新定义addEventListener等方法来实现(参考此问题的示例)。

第三,你不应该忘记间隔和超时,可以使用与前面相同的方法处理它们(包装setTimeout等)(在这里找到它)。

当然,这取决于页面中运行哪些脚本,可能会有很多东西留下。因此,当用户单击链接时,您可以在歌曲未播放时刷新页面(可能是在曲目之间进行转换)。明白了吗?还有很多工作要做,但这可能一无所获。所以,在所有这些理论之后,我会使用iframe。因为,您知道,例如:如果您网站的某些脚本包装任何js函数(就像我们在第二和第三个例子中所做的那样),那么ajaxing将在该函数上堆叠包装调用,这真的很糟糕。


虽然这样做看起来很有趣,但像这样的解决方案非常复杂,未来肯定会出现问题。虽然有时候这样做是值得冒险的,但在这种情况下,有一种更简单的解决方案。 - Flip Vernooij
正因为如此,我在答案中建议不要采用这种方法。 - Serge Seredenko

-1

如果您不介意,我想问您几个问题并在您回答时编辑这个响应。

原因是我认为您在开始这个项目时做了一些不方便的架构决策。从您的描述中,我认为您在单击a标签时加载静态html页面,如果不是,请告诉我您的后端技术是什么?

您应该将逻辑理想地分为前端和后端,并将前端分成模型、视图和控制器,不一定要使用框架或通过这种方式进行(或MVVM,如angular所做的那样)关于如何加载数据的一些快速建议,不要直接注入html,而是使用后端技术向前端发送json或xml,并解析它以显示您的html,在位于前端的模板上,而不是发送您的dom,这样做是不必要且昂贵的。当您拥有后端时,尝试在黑盒环境中构建您的持久层,并通过简单的API调用操作器方法,这样做会更加清洁,执行速度更快,更可靠。同样,这样做可以轻松地重复使用API层,当您构建移动本机应用程序时。

在CSS和JS上进行正则表达式比较听起来像是一个非常糟糕的hack,我同意,使用iframes会更合适,但是我需要更多信息来讨论您的整体设置,并希望从更广泛的角度帮助您。

更新:

我理解为什么页面可能具有不同的CSS,但我假设您的音乐播放器JS应该是附加了不同媒体ID的相同源。在这种设置下,在您的Drupal数据库中(我假设它是MySql),为您的“音乐播放器”页面制作自定义表格,除了标准的id索引条目以及created_at、modified_at等之外,还有一个字段用于可播放的来源。

在您的Drupal前端模板中,创建实际播放器的位置,将此源ID从您的数据库中写入。这样,您就可以为音乐页面拥有一个页面。对于CSS,请将所有内容保存在一个文件中,也许使用类似SASS或LESS的东西来编译您的CSS文件,以使一切井然有序。

简而言之,让您的Drupal端,PHP编写带有嵌入式JS的HTML页面,并通过PHP变量将ID传递到前端,因为PHP渲染发生在服务器端,当DOM与您的JS一起加载时,页面ID将存在。希望这可以帮助您,如果您有更多问题,请告诉我。


感谢您的输入,但我不太明白您想表达什么。即使我使用骨架或角度,我仍然会面临页面相关脚本和样式的问题。您有什么具体问题吗?:) 暂时点赞 <3 - Alex
嘿,谢谢。我问的是你的后端,也就是js和css运行的地方,是在一个简单的apache/nginx/jetty等web服务器上还是伴随着像php、java或nodejs这样的后端语言。根据这个情况,我会建议你更好地组织内容服务部分,以便你不会遇到只能使用iframes的问题。 - sed
正如我所写,我们使用Drupal,因此使用PHP。然而,语言并不能解决我的问题,即不同的页面可能具有不同的脚本。 - Alex
谢谢您的时间,但是您完全没有理解问题的所在 :) 没关系。 - Alex
不用谢,感谢你的反对票。我理所当然该被投票否决,因为至少我尝试过帮助。 - sed

-1

就像你所说的,

使用iframe可能可以解决这个问题以及其他问题: 当您首次单击站点上的链接时,页面内容会被一个iframe替换,该iframe只加载页面。音频播放器位于原始dom中,即在iframe之外。单击iframe内的链接可以被捕获并在历史记录API中使用。

您也可以通过ajax实现类似的操作。将所有需要替换的内容放在一个容器中,并根据ajax响应替换该容器的内容。不要触碰该容器之外的内容。我认为这也可以解决您的性能问题。


由于新加载的页面可能具有不同的CSS和JS,因此我们必须将当前脚本、样式和链接元素与ajax响应文本(丑陋的正则表达式)进行比较,并仅添加新的、尚不存在的元素。通过这样做,加载另一个页面不会删除/移除/撤消一旦执行的脚本。这可能会成为性能问题(而反对标记的正则表达式无论如何都是)。 - Alex
但是与在iframe本身中加载整个页面的CSS和JS元素相比,这将是更可取的。 - Sahil Kanani
我认为你没有完全理解问题的实质。通过AJAX加载内容并不是什么大问题,但JS和CSS怎么办呢?请仔细再次阅读我的问题。 - Alex
具体而言,我假设您的用户以某种方式上传声音文件,您需要将这些文件存储在数据库中,那么您如何与数据库交互?您需要一个服务器端来完成此操作,前端JavaScript无法直接访问数据库。如果您的内容都是静态的,仍然可以利用服务器端使添加内容更加容易。 - sed
好的,我明白你的问题,但我想以更深入的方式帮助你,因为iframes并不能完全解决你的问题,你需要始终拥有一个坚实的架构来未雨绸缪你的应用程序。你想在Skype或其他什么地方聊聊吗?如果你愿意,我很乐意提供帮助。 - sed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接