寻求关于如何从视图中解耦JS代码的建议
本文关键字:代码 JS 解耦 于如何 视图 | 更新日期: 2023-09-27 18:13:35
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…因为我看到你已经这么做了。这是一条正确的路!=)
不要担心可维护性,因为解耦是一种被证明的增加可维护性的方法。