寻求有关如何从视图中分离JS代码的建议

时间:2011-11-06 12:41:25

标签: c# javascript asp.net-mvc decoupling

JavaScript在大多数Web解决方案中扮演着越来越重要的角色,但我发现将JS代码与视图细节分离要比服务器端代码更难。

人们使用什么技术来解耦JS代码,以减少维护负担并使其尽可能适应次要视图变化?

为了提供一个具体的例子,我有一个类似于以下内容的视图:

<div id="signin" class="auth">
    <h2>Sign in</h2>
    <div id="resultbox" class="box" style="display: none;"></div>

    <div class="form">
        <p>Required fields are marked <span class="yellow">*</span></p>
        <form action="@Url.Action( MVC.Account.Authenticate() )" method="post" id="authform">
            <label for="Identification">Alias or email <span class="yellow">*</span></label></p>
            @Html.TextBoxFor( m => m.Identification, new { size="22", tabindex="1" } )

            <label for="Password">Password <span class="yellow">*</span></label></p>
            @Html.PasswordFor( m => m.Password, new { size="22", tabindex="2" } )

            <a href="#" class="but_styled" id="btn_signin" tabindex="3">Sign in</a>
        </form>
    </div>
</div>

JS部分分为两个文件 - 第一个是我的“业务逻辑”类,第二个主要用于连接:

(function (pp, $, undefined) {
    pp.account = {};

    function hideResultBox() {
        var box = $('#resultbox');
        box.hide();
        box.removeClass('info_box').removeClass('error_box');
    }
    function showResultBox(result) {
        var box = $('#resultbox');
        if (result.Success === true) {
            $('#resultbox_content').html(result.Message);
            box.addClass('info_box').show();
        } else {
            $('#resultbox_content').html(result.Message);
            box.addClass('error_box').show();
            var messages = '';
            for (var error in result.Errors) {
                messages += '<li>' + result.Errors[error] + '</li>';
            }
            if (messages !== '')
                $('#resultbox_content').append('<br /><ul>' + messages + '</ul>');
        }
    }

    pp.account.authenticate = function (data) {
        hideResultBox();
        $.post('/account/authenticate', data, function (result) {
            showResultBox(result);
            if (result.Success === true) {
                setTimeout(function () { window.location = result.Url; }, 1000);
            }
        });
    };
})(window.pressplay = window.pressplay || {}, jQuery);

接线部分:

$(document).ready(function () {
    $('#signin a').live('click', function () {
        var form = $(this).closest('form').serialize();
        pressplay.account.authenticate(form);
        return false;
    });
});

上面代码的问题在于它与视图的外观(必须存在的元素ID,结构等)有多紧密关系,但我对如何改进它没有好的想法。

在我看来,如果我继续沿着这条路走下去,JS文件最终会成为一堆混乱的正确封装逻辑,并结合各种特定于视图的东西。

这是我希望做的最好的,还是我可以采用任何技术来避免一些混乱?

我自己关于如何改进这个的想法围绕构建某种服务器端生成的“元素选择器”JS类,这样我就可以编写JS而不需要对类和元素id使用尽可能多的字符串引用。但我不确定如何产生这种情况,或者最终是否会更糟糕。

3 个答案:

答案 0 :(得分:3)

一些想法:

  • 不要将功能基于元素“id”值,除了视图功能确实涉及“自然”唯一的元素。尽可能使用类。
  • 使用“data-”属性将功能配置信息从HTML传递到JavaScript。 (但是不要把代码放在你的“数据 - ”属性中;在我看来,这是一个非常糟糕的主意。对不起,Knockout的粉丝。对他自己的每一个。)
  • 使用事件发布/订阅系统在功能“包”之间进行通信,以控制相互依赖性。
  • 使用<body>类来表征不同类型的页面,以提高“布线”的效率。这样,功能代码可以非常快速地判断是否需要考虑给定页面。

编辑 - 澄清最后一个:假设您有一些与<form>页面有关的功能,例如日期选择器,或自动完成输入,或其他像这样的东西。有时,某些功能仅对表单的某些有意义。在这种情况下,使用body类可以很容易地弄清楚一个特性是否应该费心去查看DOM以便影响元素:

if ($('body').is('.password-form')) { 
  // perform specific initializations
}

我目前参与的网络应用程序并不是太大,但它也不是一件容易的事。我发现我可以为整个站点保留一个大的JavaScript集合并在每个页面上包含相同的内容,而且我没有任何性能问题(目前)(IE7很慢,但这种技术不是那)。

答案 1 :(得分:1)

javascript仍然是您视图的一部分,所以我不相信设计太糟糕,让您的javascript与您的视图交织在一起。

至于可以做些什么来让生活更轻松,我认为你真的需要做任何事情来找到常见的javascript编码情况,并将它们重构出视图,并进入一个可以使用它的公共库并重复使用。例如,如果您将hideResultBox重写为如下所示:

function hideElement(var jqElementSelector, var cssClass1, var cssClass2 var cssClass3) {
    var element = $(jqElementSelector);
    element.hide();
    element.removeClass(cssClass1).removeClass(cssClass2).removeClass(cssClass3);
}

然后你可以在这个视图中替换你的电话:

CommonLib.hideElement('#resultbox', 'info_box', 'error_box');

这样至少你没有那么多的javascript来维护。它还可以更容易地从服务器生成javascript调用点,因为你没有传递逻辑,只是名字和&amp;或者ids,而不必担心在你的javascript逻辑中丢失任何类型的javascript intellisense能力。

答案 2 :(得分:1)

而不是ID,我会用更多的“功能方式”来思考 ...... 也就是说,首先考虑一下javascript代码的功能是什么, 然后以您的视图可以使用的方式创建代码。

你看到了区别吗?

你的方式是:首先查看,然后查看javascript代码...我的建议是:首先是javascript,然后是视图元素。这样你就可以确定你正在编写一个可重用的javascript代码库。

不使用ID,而是使用类。使代码像是一个通用的lib,你可以重用。不需要固定的结构,例如“.myClass div a”... div正在杀死可重用性......用一些内部类替换它:“。myClass .innerClass a”,这样你就可以将类应用到你的视图中,而不是让视图主宰代码。

尽量减少直接放在视图中的javascript代码。只需对自己的库使用方法调用,使用简单的描述性方法名称。尝试将您的JavaScript放在一起。尽量不要使用声明性的javascript ...因为我看到你已经这样做了。这是要走的路! =)

不要担心可维护性,因为解耦是提高可维护性的有效方法。