2

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 的大量字符串引用。但我不确定如何生成它,或者最终维护它是否会更糟。

4

3 回答 3

3

一些想法:

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

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

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

我目前参与的 Web 应用程序不是太大,但也不是微不足道的。我发现我可以为整个网站保留一大堆 JavaScript 并将其包含在每个页面上,而且我没有任何性能问题(目前)(IE7 很慢,但这种技术不是导致那)。

于 2011-11-06T13:39:42.873 回答
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 调用点,因为您没有传递逻辑,只是名称和或 id,并且不必担心在您的 javascript 逻辑中失去任何类型的 javascript 智能感知能力。

于 2011-11-06T13:39:11.467 回答
1

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

你看得到差别吗?

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

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

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

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

于 2011-11-06T13:39:18.363 回答