5

对于一个单页应用程序,我在其中更改哈希并加载并仅更改页面的内容,我试图决定如何管理每个“页面”可能需要的 JavaScript。

我已经有了一个历史模块来监控位置散列,看起来像domain.com/#/company/about,还有一个 Page 类,它将使用 XHR 获取内容并将其插入内容区域。

function onHashChange(hash) {
    var skipCache = false;
    if(hash in noCacheList) {
        skipCache = true;
    } 
    new Page(hash, skipCache).insert();
}


// Page.js
var _pageCache = {};
function Page(url, skipCache) {

    if(!skipCache && (url in _pageCache)) {
        return _pageCache[url];
    }
    this.url = url;
    this.load();

}

缓存应该让已经加载的页面跳过 XHR。我还将内容存储到 documentFragment 中,然后在插入 new 时将当前内容从文档中拉出Page,因此浏览器只需为片段构建 DOM 一次。

如果页面具有时间敏感数据,则可能需要跳过缓存。

以下是我需要帮助决定的内容:很可能任何被加载的页面都会有一些自己的 JavaScript 来控制页面。就像页面将使用选项卡、需要幻灯片放映、有某种动画、有 ajax 表单或你有什么一样。

将 JavaScript 加载到页面中的最佳方法到底是什么?在我从 XHR 返回的 documentFragment 中包含脚本标签?如果我需要跳过缓存并重新下载片段怎么办。我觉得第二次调用完全相同的 JavaScript 可能会导致冲突,比如重新声明相同的变量。

更好的方法是在获取新脚本时将脚本附加到头部Page?这将要求原始页面知道所有其他页面可能需要的所有资产。

除了知道包含所有内容的最佳方式之外,我是否不需要担心内存管理以及将这么多不同的 JavaScript 位加载到单个页面实例中的可能泄漏?

4

7 回答 7

1

如果我理解正确,您正在尝试使用一个当前已经为正常导航制作的页面的网站,并且您想通过 ajax 将它们拉下来,以节省页面重新加载?

那么,当这种情况发生时,您不需要重新加载这些页面的脚本标签,除非它们尚未加载到页面上?

如果是这种情况,您可以尝试在将新的 html 插入 dom 之前从页面中获取所有标签:

//first set up a cache of urls you already have loaded.
var loadedScripts = [];

//after user has triggered the ajax call, and you've received the text-response
function clearLoadedScripts(response){
   var womb = document.createElement('div');
   womb.innerHTML = response;
   var scripts = womb.getElementsByTagName('script');
   var script, i = scripts.length;
   while (i--) {
      script = scripts[i];
      if (loadedScripts.indexOf(script.src) !== -1) {
          script.parentNode.removeChild(script);
      }
      else {
          loadedScripts.push(script.src);
      }
   }

   //then do whatever you want with the contents.. something like:
   document.body.innerHTML = womb.getElementsByTagName('body')[0].innerHTML);

}
于 2010-05-20T04:15:15.100 回答
1

哦,男孩,你很幸运。我只是为自己的项目做了所有这些研究。

1:您应该使用的哈希事件/管理器是 Ben Alman's BBQ: http ://benalman.com/projects/jquery-bbq-plugin/

2:要让搜索引擎爱上你,你需要遵循一套非常明确的规则: http ://code.google.com/web/ajaxcrawling/docs/specification.html

我发现这个很晚了,我不得不放弃我的很多代码。听起来你也将不得不废弃一些,但结果你会从中得到更多。

祝你好运!

于 2010-06-07T05:14:54.337 回答
0

您是否可以控制正在加载的那些页面?如果没有,我建议将加载的页面插入 IFrame。

将页面脚本从上下文中取出并将它们插入头部或将它们添加到另一个 HTML 元素可能会导致问题,除非您确切知道页面是如何构建的。

如果您可以完全控制正在加载的页面,我建议您将所有 HTML 转换为 JS。听起来可能很奇怪,但实际上,HTML->JS 转换器并不遥远。您可以从Pure JavaScript HTML Parser开始,然后让解析器输出 JS 代码,例如使用 JQuery 构建 DOM。

前段时间我实际上正打算在我开始开发的 webapp 上走这条路,但现在我把它交给了一个承包商,他将我所有的纯 JS 页面都转换为 HTML+JQuery,不管他的日常工作如何高效,我不在乎,但我真的很喜欢那种纯粹的 JS webapp 方法,并且一定会尝试。

于 2010-05-07T18:13:04.850 回答
0

我从来没有建立过这样的网站,所以我不知道这是否是最佳实践,但我会在响应中放入某种控制信息(如注释或 HTTP 标头),并让加载程序脚本处理冗余/依赖关系检查并将脚本标签添加到标题中。

于 2010-05-07T17:15:42.017 回答
0

就个人而言,我会传输 JSON 而不是原始 HTML:

{
    "title": "About",
    "requires": ["navigation", "maps"],
    "content": "<div id=…"
}

这使您可以将元数据(如所需的脚本数组)与内容一起发送。<head>然后,您将使用脚本加载器(如上面提到的其中一个或您自己的)来检查哪些已加载,并在呈现页面之前拉下未加载的那些(将它们插入到 中)。

我不会在页面特定的逻辑中包含内联脚本,而是在需要特殊处理的元素上使用预先确定的类、ID 和属性。您可以触发“onrender”事件或让每个逻辑注册一个 on-render 回调,页面加载器将在第一次渲染或加载页面后调用该回调。

于 2010-06-07T22:14:33.357 回答
0

对我来说,这听起来像是您从一开始就创建了一个单页应用程序(即不重构现有站点)。

我能想到的几个选择:

  1. 服务器控制包含哪些脚本标签。通过 XHR 请求传递已加载脚本标签的列表,并让服务器整理出需要加载哪些附加脚本。
  2. 预先加载所有脚本(可能在页面加载后将它们添加到 DOM以节省时间)然后忘记它。对于需要初始化 UI 的脚本,只需让每个请求的页面调用都包含一个脚本标记,该标记使用页面名称调用全局 init 函数。
  3. 让每个请求的页面调用一个处理加载/缓存脚本的 JS 函数。这个函数可以从全局范围访问,看起来像这样:require_scripts('page_1_init', 'form_code', 'login_code') 然后让函数保留一个加载脚本的列表,并且只为尚未加载的脚本附加 DOM 脚本标签。
于 2010-05-22T18:11:06.520 回答
0

您可以使用像 YUI Loader、LAB.js 或其他像jaf这样的脚本加载器

Jaf 为您提供了加载视图(HTML 片段)及其各自的 js、css 文件以创建单页应用程序的机制。查看示例待办事项列表应用程序。虽然它不完整,但仍有许多有用的库可供您使用。

于 2010-06-05T06:59:19.287 回答