我应该使用 iframe 而不是 ajax 吗?
Should I use an iframe rather than ajax?
我们正在构建一个带有音频播放器的 Drupal 站点,该播放器应该在您浏览页面时继续播放(类似于 soundcloud)。
目前我们正在使用 AJAX 加载点击 <a>
的网站并将 HTML 注入页面并使用 history.js 操纵位置。
虽然有一个主要的缺点:
由于新加载的页面可能有不同的 CSS 和 JS,我们必须将当前的脚本、样式和 link 元素与 AJAX 响应文本进行比较(丑陋regex) 并仅添加新的但不存在的元素。通过这样做,加载另一个页面将不会 delete/remove/undo 一旦执行脚本。这可能会成为一个性能问题(尽管 regex 无论如何都是针对标记的)。
使用 iframe 可以解决这个问题和其他问题:
当您第一次点击网站上的 link 时,页面内容会被 iframe 替换,它只会加载页面。音频播放器在原始 DOM 中,即在 iframe 之外。在 iframe 中单击 link 也可以在历史记录 API 中捕获和使用。
所以,虽然我从来没有想过我会这么想:我认为使用 iframe 可能是更好的选择,不是吗?
PS: 我的主要问题是我无法控制网站上不同的页面有不同的脚本,样式真的没问题。如果只有一个巨大的静态 JS 和 CSS 整个网站,我没有问题。
更新
iframe 解决方案工作正常,但在 iOS 中除外。 Iframes 漏洞百出。不过,我认为我们将采用 iframe 解决方案。
你可以尝试做一些奇怪的事情。
首先,您可以将 window
对象与新对象进行比较并删除所有额外属性 (here's an example)。 document
、HTMLElement
、Array.prototype
对象和其他对象也可以做同样的事情,它们可能通过脚本进行扩展。这样你就可以消除很多定义的东西,垃圾收集器会在某个时候丢弃它。
其次,您想要删除所有事件侦听器。这可以通过重新定义 addEventListener
等 (refer to this question for example).
第三,你不应该忘记间隔和超时,这可以使用与前一个方法相同的方法来处理(包装 setTimeout
等)(found it here).
当然会剩下很多东西,这取决于页面中有哪些脚本运行。因此,当用户在未播放歌曲时单击 link(可能是曲目之间的过渡)时,您可以刷新页面。看?有很多工作要做,而这可能一无所获。所以在所有这些理论之后我会使用 iframe。因为,你知道,例如:如果你网站的一些脚本包装了任何 js 函数(就像我们在第二和第三中所做的那样),那么 ajaxing 会堆积对该函数的包装调用,这真的很糟糕。
我会说...保持简单,愚蠢。
寻求 iframe 解决方案,我知道它会扼杀你的一部分灵魂,但它是解决你的问题的最简单方法,代表了将来 运行 变成问题的最低变化。
亲吻。
我看不出您不应该使用 iframe 的理由。我认为使用 iframe 将页面嵌入您的网站很好。这就是 iframe 的用途。
iframe 过去对 SEO 不利,但如今网络爬虫通常可以在您的网站和 iframe 内容之间穿梭。
使用 iframe 比使用 "ugly regex" 对您来说更容易、更简单。为什么不保持简单,对吧? KISS principle
我想问您几个问题,如果您不介意的话,我会在您回复时编辑此回复。
这样做的原因是我相信您在开始这个项目时做出了一些不方便的架构决策。根据您的描述,我假设您在单击标签时加载静态 html 页面,如果不是,您的后端技术是什么?
理想情况下,您应该将逻辑分为前端和后端,并将您的前端分为模型、视图和控制器,不一定要使用框架或这样做(或 MVVM,如 angular做)关于如何加载数据的一些快速建议,不要直接注入 html,使用后端技术将 json 或 xml 发送到前端,并将其解析为在驻留在前端的模板上显示您的 html,而不是将您的 dom 发送下来,这样做会不必要地缓慢且昂贵。当你有后端时,尝试在黑盒环境中构建你的持久层,并通过简单的 API 调用操纵器方法,这样它会更干净,执行速度更快,更可靠。同样,当您构建移动原生应用程序时,您只需重新使用 API 层。
css 和 js 上的正则表达式比较听起来完全是个糟糕的 hack,我同意,使用 iframe 会更合适table,但同样,我需要更多信息来讨论您的整体设置,并希望能从更广阔的角度帮助您。
更新:
我理解为什么页面可能不同 css 但我假设您的音乐播放器 js 应该是相同的来源,但附加了不同的媒体 ID。假设这个设置,在你的 drupal 数据库中,我假设它是 MySql,为你的 "music player" 页面创建一个自定义的 table,除了标准的 id 索引条目和 created_at, modified_at 等,为您的可播放源设置一个字段。
在创建实际播放器的 Drupal 前端模板上,从数据库中写入此源 ID。这样你的音乐页面就只有一页了。对于 CSS 将所有内容保存在一个文件中,也许使用 SASS 或 LESS 之类的东西来编译您的 css 文件,以使所有内容更有条理。
在要点上,让你的 drupal 端,php 使用嵌入式 JS 编写你的 html 页面,并通过 PHP 变量将 ID 从数据库传递到前端,因为 PHP 渲染发生在服务器端,当 DOM 与您的 JS 一起加载时,页面 ID 将出现。希望这对您有所帮助,如果您还有其他问题,请告诉我。
正如你所说,
使用 iframe 可以解决这个问题和其他问题:
当您第一次单击站点上的 link 时,页面内容将被仅加载页面的 iframe 替换。音频播放器在原dom, i. e.在 iframe 之外。在 iframe 中单击 link 也可以在历史 api 中捕获和使用。
你可以用 ajax 做类似的事情。将所有需要替换的内容放在一个容器中,根据ajax响应替换该容器的内容即可。不要触摸该容器外的内容。我认为这也将解决您的性能问题。
我们正在构建一个带有音频播放器的 Drupal 站点,该播放器应该在您浏览页面时继续播放(类似于 soundcloud)。
目前我们正在使用 AJAX 加载点击 <a>
的网站并将 HTML 注入页面并使用 history.js 操纵位置。
虽然有一个主要的缺点:
由于新加载的页面可能有不同的 CSS 和 JS,我们必须将当前的脚本、样式和 link 元素与 AJAX 响应文本进行比较(丑陋regex) 并仅添加新的但不存在的元素。通过这样做,加载另一个页面将不会 delete/remove/undo 一旦执行脚本。这可能会成为一个性能问题(尽管 regex 无论如何都是针对标记的)。
使用 iframe 可以解决这个问题和其他问题:
当您第一次点击网站上的 link 时,页面内容会被 iframe 替换,它只会加载页面。音频播放器在原始 DOM 中,即在 iframe 之外。在 iframe 中单击 link 也可以在历史记录 API 中捕获和使用。
所以,虽然我从来没有想过我会这么想:我认为使用 iframe 可能是更好的选择,不是吗?
PS: 我的主要问题是我无法控制网站上不同的页面有不同的脚本,样式真的没问题。如果只有一个巨大的静态 JS 和 CSS 整个网站,我没有问题。
更新
iframe 解决方案工作正常,但在 iOS 中除外。 Iframes 漏洞百出。不过,我认为我们将采用 iframe 解决方案。
你可以尝试做一些奇怪的事情。
首先,您可以将 window
对象与新对象进行比较并删除所有额外属性 (here's an example)。 document
、HTMLElement
、Array.prototype
对象和其他对象也可以做同样的事情,它们可能通过脚本进行扩展。这样你就可以消除很多定义的东西,垃圾收集器会在某个时候丢弃它。
其次,您想要删除所有事件侦听器。这可以通过重新定义 addEventListener
等 (refer to this question for example).
第三,你不应该忘记间隔和超时,这可以使用与前一个方法相同的方法来处理(包装 setTimeout
等)(found it here).
当然会剩下很多东西,这取决于页面中有哪些脚本运行。因此,当用户在未播放歌曲时单击 link(可能是曲目之间的过渡)时,您可以刷新页面。看?有很多工作要做,而这可能一无所获。所以在所有这些理论之后我会使用 iframe。因为,你知道,例如:如果你网站的一些脚本包装了任何 js 函数(就像我们在第二和第三中所做的那样),那么 ajaxing 会堆积对该函数的包装调用,这真的很糟糕。
我会说...保持简单,愚蠢。 寻求 iframe 解决方案,我知道它会扼杀你的一部分灵魂,但它是解决你的问题的最简单方法,代表了将来 运行 变成问题的最低变化。
亲吻。
我看不出您不应该使用 iframe 的理由。我认为使用 iframe 将页面嵌入您的网站很好。这就是 iframe 的用途。
iframe 过去对 SEO 不利,但如今网络爬虫通常可以在您的网站和 iframe 内容之间穿梭。
使用 iframe 比使用 "ugly regex" 对您来说更容易、更简单。为什么不保持简单,对吧? KISS principle
我想问您几个问题,如果您不介意的话,我会在您回复时编辑此回复。 这样做的原因是我相信您在开始这个项目时做出了一些不方便的架构决策。根据您的描述,我假设您在单击标签时加载静态 html 页面,如果不是,您的后端技术是什么?
理想情况下,您应该将逻辑分为前端和后端,并将您的前端分为模型、视图和控制器,不一定要使用框架或这样做(或 MVVM,如 angular做)关于如何加载数据的一些快速建议,不要直接注入 html,使用后端技术将 json 或 xml 发送到前端,并将其解析为在驻留在前端的模板上显示您的 html,而不是将您的 dom 发送下来,这样做会不必要地缓慢且昂贵。当你有后端时,尝试在黑盒环境中构建你的持久层,并通过简单的 API 调用操纵器方法,这样它会更干净,执行速度更快,更可靠。同样,当您构建移动原生应用程序时,您只需重新使用 API 层。
css 和 js 上的正则表达式比较听起来完全是个糟糕的 hack,我同意,使用 iframe 会更合适table,但同样,我需要更多信息来讨论您的整体设置,并希望能从更广阔的角度帮助您。
更新:
我理解为什么页面可能不同 css 但我假设您的音乐播放器 js 应该是相同的来源,但附加了不同的媒体 ID。假设这个设置,在你的 drupal 数据库中,我假设它是 MySql,为你的 "music player" 页面创建一个自定义的 table,除了标准的 id 索引条目和 created_at, modified_at 等,为您的可播放源设置一个字段。
在创建实际播放器的 Drupal 前端模板上,从数据库中写入此源 ID。这样你的音乐页面就只有一页了。对于 CSS 将所有内容保存在一个文件中,也许使用 SASS 或 LESS 之类的东西来编译您的 css 文件,以使所有内容更有条理。
在要点上,让你的 drupal 端,php 使用嵌入式 JS 编写你的 html 页面,并通过 PHP 变量将 ID 从数据库传递到前端,因为 PHP 渲染发生在服务器端,当 DOM 与您的 JS 一起加载时,页面 ID 将出现。希望这对您有所帮助,如果您还有其他问题,请告诉我。
正如你所说,
使用 iframe 可以解决这个问题和其他问题: 当您第一次单击站点上的 link 时,页面内容将被仅加载页面的 iframe 替换。音频播放器在原dom, i. e.在 iframe 之外。在 iframe 中单击 link 也可以在历史 api 中捕获和使用。
你可以用 ajax 做类似的事情。将所有需要替换的内容放在一个容器中,根据ajax响应替换该容器的内容即可。不要触摸该容器外的内容。我认为这也将解决您的性能问题。