javascript - 如何在复杂的 Web 应用程序中构建 Javascript 程序?

标签 javascript architecture web-applications

我有一个问题,很难描述。我正在编写一个大量使用 jQuery 和 AJAX 调用的 Web 应用程序。现在我在Javascript架构方面没有太多的经验,但是我意识到我的程序没有一个好的结构。我认为我有太多标识符指的是相同(至少或多或少)的事物。

让我们看一下构成应用程序一小部分的任意示例性 UI 小部件:该小部件可以是窗口的一部分,而窗口可以是窗口管理器的一部分:

  1. 事件处理程序使用 DOM 元素作为参数。 DOM 元素代表浏览器中的一个小部件。
  2. 很多时候我使用 jQuery 对象(基本上是 DOM 元素的包装器)来对小部件执行某些操作。有时它们会被暂时使用,有时它们会存储在变量中以供以后使用。
  3. AJAX 函数调用使用这些小部件的字符串标识符。它们在服务器端进行处理。
  4. 除此之外,我还有一个小部件类,其实例代表一个小部件。它是通过 new 运算符实例化的。

现在我对同一件事有四个不同的对象标识符,它们需要保持同步,直到重新加载页面。这似乎不是什么好事。

有什么建议吗?



编辑:
*@Will Morgan*:它是一个表单设计器,允许在浏览器中创建 Web 表单。后端是 Zope,一个 python Web 应用程序服务器。很难说得更明确,因为这是我在使用 jQuery、DOM 树和我自己的原型(prototype)类实例进行 Javascript 开发时一直观察到的一个普遍问题。

编辑2:
我认为举一个例子会有所帮助,尽管是一个人为的例子。下面您会看到一个记录器小部件,可用于将 block 元素添加到显示记录项目的网页。

makeLogger = function(){
     var rootEl = document.createElement('div');
     rootEl.innerHTML = 'Logged items:';
     rootEl.setAttribute('class', 'logger');

     var append = function(msg){
           // append msg as a child of root element.
           var msgEl = document.createElement('div');
           msgEl.innerHTML = msg;
           rootEl.appendChild(msgEl);
     };

     return {
          getRootEl: function() {return rootEl;},
          log      : function(msg) {append(msg);}
     };
};

// Usage 
var logger = makeLogger();
var foo = document.getElementById('foo');
foo.appendChild(logger.getRootEl());
logger.log('What\'s up?');

此时,我有一个围绕 HTMLDivElement(托管对象)的包装器。有了记录器实例( native 对象),我可以通过函数 logger.getRootEl() 轻松使用它。
当我手头只有 DOM 元素并且需要使用函数 makeLogger 返回的公共(public) API 执行某些操作时(例如在事件处理程序中),我遇到了困难。这就是困惑开始的地方。我需要将所有 native 对象保存在存储库或其他东西中,以便我可以再次检索。拥有从托管对象到我的 native 对象的连接(例如对象属性)会好得多。 我知道这是可以做到的,但它有一些缺点:

  • 此类(循环)引用可能会导致 IE7 之前的内存泄漏
  • 何时传递托管对象以及何时传递 native 对象(在函数中)?

现在,我使用 jQuery 的 data() 方法进行反向引用。但总而言之,我不喜欢跟踪托管对象与其 native 对应对象之间关系的方式。

您如何处理这种情况?



编辑3:
在我从阿努拉格的例子中获得了一些见解之后..
*@Anurag:*如果我正确理解了你的示例,关键点是设置正确的(不过,什么是正确的取决于你的需求)执行上下文事件处理程序。在您的例子中,这是演示对象实例,它是使用 Mootool 的 bind() 函数完成的。所以你要确保你*总是*处理包装对象(我将其称为 native 对象)而不是 DOM 对象,对吗?

给读者的提示:您并非被迫使用 Mootools 来实现此目的。在 jQuery 中,您可以使用 *$.proxy()* 函数设置事件处理程序,或者如果您使用普通的旧 Javascript,则可以利用每个函数公开的 *apply* 属性。

最佳答案

您可以使用全局注册表:

window.WidgetRegistry = {};
window.WidgetRegistry['foowidget'] = new Widget('#myID');

当 AJAX 调用返回时,他们可以获得这样的小部件:

var widgetID = data.widgetID;
if (widgetID in window.WidgetRegistry) {
    var widget = window.WidgetRegistry[widgetID];
}

对于您的 jQuery 调用:我猜它们相对便宜,因为 jQuery 会缓存对象以供以后使用。但是您可以使用 .data() 扩展上面建议的 WidgetRegistry :

var $widget = $('#myWidget');
var widgetID = 'foo';
$widget.data('widget', widgetID);

通过这种方式,您可以存储附加到每个 jQuery 对象的小部件 ID,并从全局注册表重新访问它。

测试 jQuery 对象是否有现有的小部件:

return $('#test').data('widget') &&
       ($('#test').data('widget') in window.WidgetRegistry);

请注意,这些只是建议。实际上,有很多种方法可以实现这样的整合。如果您想将代码与 jQuery 更深入地结合起来,您可以 extend the jQuery object ,这样你就可以编写如下内容:

$('#widget').widget({'foo':'bar'});
// and/or
var allWidgets = $('*:widget');
// ...

关于javascript - 如何在复杂的 Web 应用程序中构建 Javascript 程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2407872/

相关文章:

java - 哪个用Java编写的嵌入式数据库可用于简单的键/值存储?

java - 如何使用 JSF 获取用户的浏览器 ID?

javascript - 检查节点是否被完全选中

javascript - 处理异步加载的函数中的无限循环

javascript - 使用 XDomainRequest 调用跨域 AJAX 时出现权限被拒绝错误

architecture - CQRS 中的命令必须是异步的吗?

java - GWT:应用程序架构问题

rest - Golang rest API 项目结构

web-applications - 基于UML的Web建模: model the login process?

javascript - Node.js 中的 ES6 风格子进程