如何在复杂的Web应用程序中构建JavaScript程序的结构?
如何在复杂的Web应用程序中构建JavaScript程序的结构?
我有一个问题,很难描述。我正在编写一个使用jQuery和AJAX调用的Web应用程序。现在我在Javascript架构方面没有太多经验,但我意识到我的程序结构不好。我认为我有太多引用相同(至少多多少少)东西的标识符。
让我们看一个任意的示例UI小部件,它构成了应用程序的一小部分:该小部件可能是一个窗口的一部分,而该窗口可能是一个窗口管理器的一部分:
- 事件处理程序使用DOM元素作为参数。DOM元素表示浏览器中的小部件。
- 很多时候,我使用jQuery对象(基本上是DOM元素的包装器)来对小部件进行操作。有时它们是短暂使用的,有时它们被存储在变量中以备后用。
- AJAX函数调用使用字符串标识符来标识这些小部件。它们在服务器端进行处理。
- 此外,我还有一个小部件类,其实例表示一个小部件。它通过new运算符进行实例化。
现在,我对于同一个东西有四个不同的对象标识符,需要在页面重新加载之前保持同步。这似乎不是一件好事。
有什么建议吗?
编辑:
*@Will Morgan*:这是一个允许在浏览器中创建Web表单的表单设计器。后端是Zope,一个Python Web应用程序服务器。由于这是一个使用jQuery、DOM树和我的自定义原型类实例进行JavaScript开发时经常遇到的一般性问题,很难更加明确。
编辑2:
我认为提供一个例子会有所帮助,尽管它是一个人为的例子。下面是一个可以用于在Web页面中添加一个块元素以显示日志项的日志小部件。
makeLogger = function(){ var rootEl = document.createElement('div'); rootEl.innerHTML = 'Logged items:'; rootEl.setAttribute('class', 'logger'); var append = function(msg){ // 将msg作为根元素的子元素附加。 var msgEl = document.createElement('div'); msgEl.innerHTML = msg; rootEl.appendChild(msgEl); }; return { getRootEl: function() {return rootEl;}, log : function(msg) {append(msg);} }; }; // 使用 var logger = makeLogger(); var foo = document.getElementById('foo'); foo.appendChild(logger.getRootEl()); logger.log('What\'s up?');
此时,我有一个HTMLDivElement的封装器(托管对象)。有了logger实例(本机对象),我可以通过函数logger.getRootEl()轻松地使用它。
当我只有DOM元素并且需要使用函数makeLogger返回的公共API执行某些操作时,我会陷入困境(例如,在事件处理程序中)。这就是混乱开始的地方。我需要将所有本机对象存储在一个仓库中,以便以后可以检索。如果能够有一个从托管对象返回到本机对象的连接(例如,一个对象属性),那将会更好。
我知道这是可以做到的,但它有一些缺点:
- 这种(循环)引用可能会导致内存泄漏,尤其是在IE7中
- 什么时候传递托管对象,什么时候传递本机对象(在函数中)?
目前,我使用jQuery的data()方法进行反向引用。但总体而言,我不喜欢在托管对象与其本机对应物之间保持关系的方式。
您如何处理这种情况?
编辑3:
从Anurag的例子中,我获得了一些见解..
*@Anurag*:如果我正确理解你的例子,关键点是为事件处理程序设置正确(根据你的需求而定)的执行上下文。在你的情况下,这是演示对象实例,它是通过Mootool的bind()函数完成的。所以你确保始终处理包装对象(我称之为本机对象),而不是DOM对象,对吗?
读者请注意:您不必使用Mootools来实现这一点。在jQuery中,您可以使用*$.proxy()*函数设置事件处理程序,或者如果您使用的是普通的Javascript,您可以利用每个函数都公开的*apply*属性。