【发布时间】:2011-01-25 08:35:55
【问题描述】:
我有一个不容易描述的问题。我正在编写一个强烈使用 jQuery 和 AJAX 调用的 Web 应用程序。现在我在 Javascript 架构方面没有太多经验,但我意识到我的程序没有一个好的结构。我认为我有太多标识符指代相同(至少或多或少)的事物。
让我们看一下构成应用程序一小部分的任意示例 UI 小部件:小部件可能是窗口的一部分,而窗口可能是窗口管理器的一部分:
- 事件处理程序使用 DOM 元素作为参数。 DOM 元素代表浏览器中的一个小部件。
- 很多时候我使用 jQuery 对象(基本上是 DOM 元素的包装器)来处理小部件。有时它们会暂时使用,有时它们会存储在变量中以供以后使用。
- AJAX 函数调用对这些小部件使用字符串标识符。它们在服务器端进行处理。
- 除此之外,我还有一个小部件类,其实例代表一个小部件。它通过 new 运算符实例化。
现在我有四个不同的对象标识符用于同一事物,需要保持同步,直到重新加载页面。这似乎不是一件好事。
有什么建议吗?
编辑:
*@Will Morgan*:它是一个表单设计器,允许在浏览器中创建 Web 表单。后端是 Zope,一个 Python Web 应用服务器。很难说得更清楚,因为这是我在使用三重奏 jQuery、DOM 树和我自己的原型类实例进行 Javascript 开发时一直观察到的一个普遍问题。
EDIT2:
我认为做一个例子会有所帮助,尽管是一个人为的例子。下面是一个记录器小部件,可用于将块元素添加到显示记录项目的网页。
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(托管对象)进行了包装。有了手头的记录器实例(本机对象),我可以通过函数 logger.getRootEl() 轻松使用它。
当我手头只有 DOM 元素并且需要对函数 makeLogger 返回的公共 API 做一些事情时(例如在事件处理程序中),我会遇到困难。这就是混乱开始的地方。我需要将所有本机对象保存在存储库或其他东西中,以便我可以再次检索。将托管对象与我的本机对象建立连接(例如对象属性)会更好。
我知道它可以做到,但它有一些缺点:
- 这类(循环)引用可能会导致内存泄漏到 IE7
- 何时传递托管对象以及何时传递本机对象(在函数中)?
现在,我使用 jQuery 的 data() 方法进行反向引用。但总而言之,我不喜欢必须跟踪托管对象与其本地对象之间关系的方式。
您如何处理这种情况?
EDIT3:
在我从 Anurag 的示例中获得了一些见解之后..
*@Anurag:* 如果我正确理解了您的示例,那么关键是设置正确的(不过,正确的取决于您的需要)执行上下文事件处理程序。在您的情况下,这是演示对象实例,它是使用 Mootool 的 bind() 函数完成的。所以你要确保你*总是*处理包装对象(我称之为本机对象)而不是 DOM 对象,对吧?
给读者的提示:您不必使用 Mootools 来实现这一点。在 jQuery 中,您可以使用 *$.proxy()* 函数设置事件处理程序,或者如果您使用普通的旧 Javascript,您将使用每个函数公开的 *apply* 属性。
【问题讨论】:
-
它是一个什么样的网络应用程序?有任何示例以便我们提供帮助吗?
-
所以用更简单的语言来说,“应该如何构造代码和数据来组合/推断/执行对一组不断变化的 UI 元素事件的适当响应 - 并应对集合中内容的动态变化元素 - 出于 IE 内存管理的原因,元素需要由其他对象和函数通过键/名称间接引用(而不是对象之间潜在的循环直接引用) - 并且元素具有多个键/名称;并且元素也既有额外的自定义包装类,也有 jQuery 包装类”?
-
@martinr:你在跟我开玩笑,不是吗?如此妖孽的气息,怎能再平淡无奇?也许是因为我不是母语人士:)
-
LOL 好吧,更短,更简洁。
-
这是正确的!图书馆无所谓。您可以使用任何库或 POJO(普通的 Javascript 对象)来做同样的事情。但是像你说的重要的事情是将
execution context设置为本地对象(或与本地对象有朋友的任何其他地方)。
标签: javascript architecture web-applications