更好的 JavaScript 组织和执行:不显眼的方式 - 自执行匿名函数

Better JavaScript Organisation and Execution The Unobtrusive Way - Self-Executing Anonymous Func

提问人:Jammer 提问时间:5/8/2013 最后编辑:Jammer 更新时间:5/8/2013 访问量:176

问:

我正在慢慢地对 JavaScript 有了更好的理解,但我被困在如何最好地处理这个特定的组织/执行场景上。

我来自C#背景,习惯于使用命名空间,所以我一直在阅读如何使用JavaScript实现这一点。我已经将已经开始成为一个大型 JavaScript 文件,并将其拆分为更合乎逻辑的部分。

我决定为页面特定的 JavaScript 每页一个文件,其中包含两个或更多页面共有的任何内容,例如可重用的实用程序函数,位于另一个命名空间和文件中。

目前这对我来说很有意义,并且似乎是一个受欢迎的选择,至少在开发过程中是这样。无论如何,我将使用捆绑工具将这些不同的文件组合在一起,以便部署到生产环境,因此任何使开发更合乎逻辑且更容易找到代码的东西都会更好。

由于我在处理大量自定义 JavaScript 方面缺乏经验,我在通用 JavaScript 文件中定义了一个函数,如下所示:

通用.js

$(document).ready(function () {
    var historyUrl = '/history/GetHistory/';
    $.getJSON(historyUrl, null, function (data) {
        $.each(data, function (index, d) {
            $('#history-list').append('<li>' + d.Text + '</li>');
        });
    });
});

这显然远非理想,因为它特定于应用程序中的单个页面,但在每个页面请求上都执行,如果不是完全愚蠢的话,这完全毫无意义且效率低下。因此,这促使我首先开始阅读命名空间。

经过一番阅读,我现在已将其移动到特定于页面的文件中,并像这样重写:

从 common.js 移动到 historyPage.js

(function(historyPage, $, undefined) {

    historyPage.GetHistory = function () {
        var historyUrl = '/history/GetHistory/';
        $.getJSON(historyUrl, null, function (data) {
            $.each(data, function (index, d) {
                $('#history-list').append('<li>' + d.Text + '</li>');
            });
        });
    };
    }( window.historyPage = window.historyPage || {}, jQuery ));

我在jQuery Enterprise页面上找到了这种模式。我还不打算假装完全理解它,但它似乎是一种非常流行且最灵活的组织和执行具有各种不同范围的 JavaScript 的方式,从而将事情排除在全局范围之外。

但是,我现在正在努力解决的是如何从执行的角度正确使用这种模式。我还试图将任何 JavaScript 排除在我的 HTML Razor 视图之外,并以一种不显眼的方式工作。

那么,我现在如何仅在它应该实际执行时调用该函数,即:仅当用户导航到网站上的“历史记录”页面并且需要该函数的结果时?historyPage.GetHistory

javascript jquery asp.net-mvc-4 unobtrusive-javascript 模块模式

评论


答:

0赞 James Montagne 5/8/2013 #1

从代码来看,最简单的测试似乎是检查您所在的页面是否包含带有 的元素。像这样的东西:idhistory-list

var $histList = $('#history-list');

if($histList.length > 0){
    // EXECUTE THE CODE
}

虽然如果它真的只需要在一个给定的页面上运行,也许它不是共享 javascript 文件的好候选者。

评论

0赞 Jammer 5/8/2013
它不在共享文件中,而是在仅包含历史记录页代码的 historyPage.js 文件中。有没有更好的方法来封装特定页面的代码?
0赞 Dagg Nabbit 5/8/2013
如果这个脚本只需要在一个页面上运行,为什么一开始就需要“命名空间”它呢?只需写一次,并且只将其包含在该页面上。如果你已经有一个全局的“命名空间”对象,那么使用——这里真的没有理由乱七八糟的 IIFE,而且听起来你肯定知道是否存在,所以应该不需要(也不需要,因为你没有使用它;不是说曾经有过,因为)。function getHistory() { ... }myNS.getHistory = function() { ... };historyPagewindow.historyPage = window.historyPage || {}undefinedvoid
0赞 Jammer 5/8/2013
我是第一次使用可能大量的 JavaScript 进行如此密集的工作。我试图用许多不同的意见和方法在看似非常浑浊的水域中航行。老实说,我对你的评论感到困惑。就像我说的,我还没有假装完全理解它。请记住,我也在尝试不引人注目地做事,我不确定我会如何或在哪里写,就我而言,我只写了一次函数,任何地方都没有重复的代码。对不起,如果我仍然很傻。function getHistory()
0赞 James Montagne 5/8/2013
@Jammer 如果它已经只包含在该页面上,那么我不确定您的实际问题是什么。在上面的问题中,您询问了如何仅在“用户导航到”历史记录页面时“运行它。但听起来这不是问题。
0赞 Jammer 5/8/2013
@JamesMontagne我在发布原始问题后发现了这种技术。我想我现在会使用这种技术,随着我获得更好的理解,我以后会处于更好的位置重新评估。感谢您的帮助。
0赞 Jammer 5/8/2013 #2

使用我在上面的问题中详述的代码,我通过执行以下操作使其正常工作:

在 _Layout.cshtml 中

    @if (IsSectionDefined("History"))
    {
      <script type="text/javascript">
          $(document).ready(function () {
            @RenderSection("History", required: false)
        });
      </script>
    }

在 History.cshtml 中

@section History
{
  historyPage.GetHistory();
}

仅当用户请求网站上的“历史记录”页时,代码才会根据需要执行。尽管上面 @Dagg Nabbit 的评论给我抛出了一个曲线球,因为我认为我走在正确的轨道上......嗯。。。