寻求关于如何从视图中解耦JS代码的建议

Seeking recommendations on how to decouple JS code from views

本文关键字:代码 JS 解耦 于如何 视图      更新时间:2023-09-26

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

一些想法:

  • 不要将功能建立在元素的id值上,除非视图特性确实涉及到"自然"唯一的元素。尽可能使用类。
  • 使用"data-"属性将特性配置信息从HTML传递到JavaScript。(但是不要在"data-"属性中添加代码;在我看来,这真是一个糟糕的主意。很抱歉,淘汰赛的粉丝们。
  • 使用事件发布/子系统在功能"包"之间进行通信,以控制相互依赖。
  • 使用<body>类来描述不同类型的页面,以提高"布线"的效率。这样,功能代码可以很快地判断是否需要考虑给定页面。

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

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

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

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智能感知能力。

代替id,我想以更的"功能方式"…也就是说,首先想想javascript代码的功能是什么,然后以一种可以被视图使用的方式编写代码。

你看出区别了吗?

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

不要使用id,而是使用类。使代码像一个通用的库,您可以重用。不需要固定的结构,例如"。myClassdiv "…"这个div正在扼杀可重用性……将其替换为一些内部类:"。myClass . innerclass a",这样你就可以把这些类应用到你的视图中,而不是让视图主导代码。

尽量减少直接放在视图中的javascript代码。使用方法调用你自己的库,使用简单和描述性的方法名。试着把你的javascript放在一起。尽量不要使用声明式javascript…因为我看到你已经这么做了。这是一条正确的路!=)

不要担心可维护性,因为解耦是一种被证明的增加可维护性的方法。