【问题标题】:Going "Stateless" and loading scripts dynamically走向“无状态”并动态加载脚本
【发布时间】:2011-07-23 02:55:21
【问题描述】:

我想知道我是否从正确的角度接近这个。

我正在构建一个 asp.net 应用程序。我正在使用 Masterpage 来查看应用程序的整体外观(您可以在下面看到代码)。

我想让菜单系统使用像 jQuery 的 .load() 函数这样的动态加载来加载内容。那很好,我把它记下来了。 .load() 函数使用innerHTML 将该内容泵入页面。如果您想在该页面上加载特定于模块的脚本和样式,这是一个问题。

我的问题是,在这样的环境中,你们如何为这些模块加载脚本?我应该在应用程序的初始加载时加载每个脚本吗?这个应用程序永远不会“那么大”,但我想确保我做对了以防万一。

MasterSheet

<div id="primaryNavigation">
    <ul>
        <li class="current"><a href="../Default.aspx">Main</a></li>
        <li><a href="../Modules/Page1.aspx">Some Overview</a></li>
        <li><a href="../Modules/Page2.aspx">Reporting</a></li>
        <li><a href="../Modules/Page3.aspx">More Reporting</a></li>
        <li><a href="../Modules/Page4.aspx">About</a></li>
    </ul>
</div>

<div id="mainContentContainer">
    <asp:ContentPlaceHolder ID="cphBody" runat="server" />
</div>

内容标签内的示例模块

<div id="container"> 
    Inside a page

    <script id="scriptToLoad" type="text/javascript">
      alert('Something');

      head.ready(function () { console.log('please print'); }); 
    </script>

</div>

<div id="includeScripts">
    ../Files/Javascript/SomeModuleSpecificJs.js
    ../Files/Javascript/SomeModuleSpecificJs1.js    
</div>

我的想法是在每个模块中设置一个div,它的 id 为“includeScripts”,并从这样的母版表中的方法加载它们。这种方法有效(显然需要一些调整)但是如果用户继续点击模块,最终每个文件都会被加载。如果是这样,我不妨将它们全部加载到母版表上。

加载 MasterPage 时运行的 JS

$navigation = $("#primaryNavigation").delegate('ul li a', 'click', function () {
                    $('#primaryNavigation').find('li').removeClass('current');
                    $(this).parent().addClass('current');

                    $('#mainContentContainer').load($(this).attr('href') + ' #container');

// Obviously this would overwrite the content from the container, this is merely proof of concept
                $('#mainContentContainer').load($(this).attr('href') + ' #includeScripts');

                    var jsArray = $('#includeScripts').text().trim().split("\n");

                    $.each(jsArray, function (index, value) {
                        $.getScript(value);
                    });

                    return false;
                });

【问题讨论】:

  • 哇,还是只有一个答案。也许尝试提出另一个更通用的问题(“我如何...”)并分析任何提供的代码 sn-ps。
  • 您的意思是母版页吗?我不知道母版表是什么...
  • @phillip 是的,母版页......对不起

标签: asp.net master-pages stateless


【解决方案1】:

我不知道.load(),但JQuery 的.html().append() 和其他一些相关函数会自动运行它们在给定HTML 中找到的任何脚本标签。如果load() 不适合您,那么使用$.get(..., function(){$('#myElement').html();}); 应该很容易。您甚至可以专门为此目的编写自己的扩展。

样式表可能是另一回事。我通常每页只使用一个样式表。

编辑

我刚刚花了一些时间阅读你的问题,我意识到我没有完全回答。

我应该在应用程序的初始加载时加载每个脚本吗?

这实际上取决于您的脚本的大小以及您希望用户与您的系统交互的方式。在this seminar 中,制作 Google Wave 的人谈论了他们是如何解决这个问题的。演讲者有一次说,“感知延迟是最重要的优化因素。”问题是,在早期版本中,他们的 javascript 文件(由 GWT 优化和编译)只有几兆字节。连接速度较慢的人(例如手机浏览器)必须等待很长时间才能下载所有这些代码,然后才能看到收件箱中的内容。他们的解决方案是在他们的代码中创建“分割点”,以便可以分块加载。可以先加载显示收件箱所需的代码,而联系人面板可以等到用户单击“联系人”。

但你可以做得太过分了。该视频中的另一位发言者表示,加载所花费的时间主要属于以下两类之一:

  • 获取您不需要的数据,并且
  • HTTP 请求过多

每次 HTTP 往返都涉及一定量的开销,因此值得加载一些您还不需要的代码,以避免在一个当您意识到自己需要它时,只需几毫秒。

既然你说:

这个应用永远不会“那么大”

... 我猜您可能主要属于后一类(HTTP 请求太多)。在这种情况下最好的做法是:

  1. 使用Chirpy 之类的工具将所有 javascript 文件合并到一个文件中(在不处于调试模式时可以自动缩小文件)。
  2. 如果您的应用程序有一个不使用所有这些 javascript 功能的登录页面,请在登录页面底部为此 javascript 文件添加一个 script 标签,以便用户的浏览器在后台下载文件,同时用户正忙于输入他们的用户名和密码。网站其余部分的母版页应仅在标准 script 标记中包含一次脚本文件。
  3. 确保您网站的缓存规则设置正确,以便用户的浏览器只请求该文件一次。
  4. 确保您的网站设置为压缩此 javascript 文件,因为 javascript(尤其是缩小的 javascript)非常适合 gzip 压缩。

完成此操作后,您应该会发现加载 javascript 文件时没有“感知延迟”。

如果您的应用程序最终会变得“那么大”,您会希望像 Google Wave 团队那样将您的程序分解为模块。但是根据您期望系统的使用方式来选择您的模块。例如,如果只有一小部分用户可能使用您的管理界面,您可能希望将所有管理 UI 代码放入一个单独的模块中,“普通”用户永远不必下载。

在决定在哪里划线时,UI 专家基本上说五分之一秒是典型人类大脑开始思考的时间点,“这有效吗?”如果用户单击一个按钮并且必须等待比这更长的时间才能看到发生的事情,那么您就达到了“感知延迟”的地步。除此之外的任何事情都会让用户越来越讨厌。

【讨论】:

  • 感谢您更新您的问题,如果我提到这不会是面向外部的应用程序,您的回答会在其中一些方面发生变化吗?所以所有用户都在同一个内部网络上。只是想了解其他开发人员是如何做这类事情的。
  • @Mike Fielden:如果仅在本地网络上使用,您可能具有更高的速度和更低的延迟,但可能不会达到数量级。这意味着在文件开始导致感知延迟之前,您将使用单个 javascript 文件方法走得更远,但总体推理不会改变。
猜你喜欢
  • 1970-01-01
  • 2014-03-10
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
相关资源
最近更新 更多