【问题标题】:ASP.NET Webforms, JavaScript in user controlsASP.NET Webforms,用户控件中的 JavaScript
【发布时间】:2012-09-06 15:12:58
【问题描述】:

在我们的解决方案(APS.NET Webforms)中正确实现 JavaScript 方面我们有点挣扎。

根据最佳实践,我们希望将所有(或至少尽可能多的)javascript 放在页面底部,以便页面首先加载 HTML 和 CSS,并提供更好的用户体验。

在我们的整个项目中有很多 jQuery 代码通常特定于某些控件,因此我们不希望在每个页面上都加载这些代码。

目前 jQuery 本身,包括 jQuery UI 都位于页面顶部,因此我们可以在控件中使用 jQuery(来自 js 文件或有时是内联代码),但是,我们希望将所有这些内容移到页面底部。我们已经在页面底部添加了一个内容占位符(“JavascriptFooter”),因此我们可以将页面中的 javascript 放置在页面的页脚中,但是我们被困在控件上。

这方面的最佳做法是什么?我们是否应该外部化所有 JS 并在 JS 中检查是否加载了控件?但是我们会一直展示太多的东西。还是有别的办法?

【问题讨论】:

  • 为什么不推迟脚本的执行,直到 DOM 准备好?即 ($(function(){ ..On Ready Code Goes Here .. });
  • ($(function(){ console.log("Works?"); })); 在头部抛出错误$ is not defined,jQuery 在底部初始化。
  • 您需要在执行该脚本之前包含 Jquery……您可以轻松地从 Google 等 CDN 中提取它。我通常在头部包含 Jquery,来自 CDN 和底部的所有其他内容。
  • 这就是胎面的重点。如何将控件中的 JS 放在页脚中,而不是将 jQuery 放在页面顶部。
  • 您想如何添加 JavaScript?您打算在控件的标记内或后面的控件代码中执行此操作吗?

标签: asp.net webforms


【解决方案1】:

首先,我建议从 CDN 加载 Jquery。这是 Google 的代码:

<script type="text/javascript">
    document.write(["\<script type='text/javascript' src='", 
    ("https:" == document.location.protocol) ? "https://" : "http://", 
    "ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'>\<\/script>"].join(''));
</script>

这样,如果访问者已在另一个网站上获得此服务,则它已经被缓存。此外,它会在从不同的主机传送时并行下载。

我也同意@ctorx - 您应该使用文档就绪执行。

此外,您可以使用ScriptManager 并在每个控件后面的代码中创建所有控件特定的 JS(如果该控件是唯一使用该 JS 的对象,这可能是一个好主意) - 所有这些代码都呈现在页面底部。

例子:

Page pg = (Page)System.Web.HttpContext.Current.Handler; // or this.Page in .ascx
ScriptManager.RegisterStartupScript(pg, typeof(Page), "myJS", "[... your code ]", true);

【讨论】:

  • 谢谢,我们确实为 jQuery(-UI) 使用 CDN,但我们仍然希望在底部加载它们。
  • 协议可以自动解析,只需输入脚本url为"//ajax.googleapis.com/..."
【解决方案2】:

我敢打赌,解决方案与使用网络表单的公司一样多。也就是说,您始终可以使用请求上下文来存储必要的脚本,然后在页面呈现之前编写它们。

您也可以使用requireJS。我不是专家,但有很多选择,它可以处理脚本加载超时、循环依赖、定义多个依赖等。

【讨论】:

    【解决方案3】:

    首先,最好的方法是将 JavaScript 从 JS 文件中的控件外部化,该文件在对您的站点的第一个请求和所有后续请求(即 site.js)时加载。然后,该文件将被浏览器缓存,用户不必像 JS 留在控件中那样一遍又一遍地下载 JS。

    接下来,您需要创建一种机制,只执行与正在执行的页面或控件相关的脚本部分。

    有几种方法可以实现这一点,但是如果我遇到你的情况,我会这样做。

    确定一个包含大部分内容的页面级元素......通常人们称之为wrapper。将自定义属性动态添加到名为“data-js”的包装器中。从页面或用户/自定义控件动态(在服务器端)设置“data-js”的值。允许它有多个由竖线 (|) 或其他字符分隔的键。

    <div class="wrapper" data-js="funtion1|function2">
         <!-- Page content goes here -->
    </div>
    

    利用 jQuery 在 DOM 就绪时查找此属性,并根据 data-js 属性中的值执行自定义 JS 函数。该函数将仅包含与当前页面或控件相关的代码。

     $(function(){
        var funcKeys = $('.wrapper').attr('data-js');
        if(funcKeys != null)
        {
            var funcs = funcKeys.split('|');
            for(var i=0; i< funcs.length; i++) {
               var funcName = eval(funcs[i]);
               if(typeof funcName == 'function') {
                    funcName();
               }
            }
        }    
    });
    

    使用这种方法,您只需要 jQuery CDN 引用、对您网站的 JS 文件的引用以及布局中的上述 sn-p 代码。

    然后您只需在站点特定的 JS 文件中包含页面/控件特定功能,如下所示:

    function function1() {
        alert("This is function 1");
    }
    
    function function2() {
        alert("This is function 2");
    }
    

    我希望这会有所帮助。

    仅供参考,我还设置了一个小提琴供您使用: http://jsfiddle.net/hh84f/1/

    【讨论】:

    • 谢谢,有趣的解决方案,我会看看。或者,可以使用相同的技术来加载特定的 JS 文件而不是执行函数。
    • 确实如此。我打算在第一次请求时获得一个可缓存的 http 命中,但如果站点有很多 JS,那么从维护的角度来看,单独的文件可能是一个更干净的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多