2011-01-20 109 views
7

我注意到JavaScript中的一个常见模式,我一直在编写,并且想知道是否已经有一个模式定义类似于最佳实践的模式?从本质上讲,它是如何获得一个DOM元素并将其包装/关联到一个JavaScript对象。以此示例为例,您需要在Web应用程序中使用过滤器。您的网页看起来是这样的:包装JavaScript对象中的DOM元素

<html> 
<head></head> 
<body> 
    <div id="filter"></div> 
</body> 
</html> 

你会然后包像这样的元素:

var myFilter = new Filter({ 
    elem: document.getElementById('filter'), 
    prop: 'stacks-test', 
    someCallback: function() { 
     // specify a callback 
    } 
}); 

和JavaScript(这里spec是传递给构造一个对象):

var Filter = function(spec) { 
    this.elem = spec.elem; 
    this.prop = spec.prop; 
    this.callback = spec.someCallback; 
    this.bindEvents(); 
}; 

Filter.prototype.bindEvents = function() { 
    var self = this; 
    $(this.elem).click(function(e) { 
     self.updateFeed(); 
    }; 
}; 

Filter.prototype.updateFeed = function() { 
    this.prop; // 'stacks-test' 
    this.callback(); 
    // ... 
    // code to interact with other JavaScript objects 
    // who in turn, update the document 
}; 

这种方法称为什么,最佳实践和注意事项是什么?

+0

我不想听起来像一个没心没肺的jQuery粉丝,但它看起来像你最好使用jQuery或类似的框架。虽然它的主要目的是帮助你选择和操作DOM,但是整个库建立在你正在讨论的DOM包装模式的基础上,所以它的插件功能和其他辅助函数自然而然地使你很容易做到这一点好。 – 2011-01-20 06:21:57

+0

我仍然需要使用构造函数,因为在一个文档中会有多个过滤器。你能告诉我一个使用jQuery和Filter对象的例子吗? – 2011-01-20 06:39:12

+0

我会尽快发布答案。另外,下次请记住在您的评论中包含@ Box9,以便我收到通知。我只是偶然发现了这个问题。 – 2011-01-20 07:19:01

回答

2

你可能会对Dojo的小部件库Dijit感兴趣 - 如果我正确理解你的问题,它基本上可以做你正在问的东西,还有更多。在Dijit中,一个小部件实际上封装了一个DOM节点,它的内容,任何定义其行为的JavaScript,以及(单独导入)CSS来设计其外观。小部件有自己的生命周期,注册表和事件(包括许多简单地映射到小部件内的节点上的DOM事件,例如myWidget.onClick可以有效地调用myWidget.domNode.onclick)。

小工具可以(但不必)在独立的HTML模板文件中定义其初始内容,通过该文件还可以将模板内节点上的事件绑定到小部件方法,以及在小部件引用模板中的特定节点。

我几乎没有在这里抓表面。如果您想了解更多关于这一点,你可以用这些参考页开始:

所有说,我不知道你最终瞄准什么,也许这对你的目的有点(考虑我把你的整个其他库),但认为它可能激起你的兴趣至少。

1

继续我对这个问题的评论,jQuery是一个潜在的工具工具,因为它已经为您的工作提供了一些基础。然而,尽管如此,它确实引入了自己的复杂性,并且并不是所有的“jQuery方法”都是平等的。我会提出一种使用jQuery作为“对象模型”的方法,但它可能会或可能不适合您的需要。


首先要做的事情。 jQuery的哲学是,你首先选择元素,使用$()或等效地jQuery()来启动所有的事情。所有的操作都是从这个开始的。与创建一个包装元素并保持对该包装器的引用的对象相比,这是一种稍微不同的思维方式,但本质上这就是jQuery为您做的。对$('#some-id')的调用抓取id为“some-id”的元素并将其包装在一个jQuery对象中。


方式一:写 “过滤器” 插件。

将您的构造函数替换为initFilter() jQuery方法。你可以通过修改jQuery原型并使用jQuery对象作为包装来实现。 jQuery的原型是由jQuery.fn引用的,所以:

jQuery.fn.initFilter = function (prop, callback) { 
    // Save prop and callback 
    this.data('filter-prop', prop); 
    this.data('filter-callback', callback); 

    // Bind events (makes sense to do this during init) 
    this.click(function() { 
     $(this).updateFeed(); 
    }); 
}; 

然后做类似的事情updateFeed()

jQuery.fn.updateFeed = function() { 
    this.data('filter-prop'); 
    this.data('filter-callback')(); 
}); 

而且使用这样的:

$('#filter').initFilter(prop, callback); 

注意updateFeed可以简单地插入到点击处理程序中以防止对jQuery名称空间造成不必要的污染。然而,像这样使用jQuery的一个优点是,如果以后需要调用某个函数,则不需要保留该对象的引用,因为jQuery将所有引用绑定到实际元素。如果你想打电话updateFeed编程,那么:

$('#filter').updateFeed(); 

然后将正确的对象上调用。


有些事情要考虑

当然有缺点这种方法。一个是所有属性,我们已经使用.data()针对元素保存的所有属性在所有jQuery函数之间共享,这些函数作用于该元素。我试图通过在属性名称前添加“filter-”来减轻这一点,但取决于对象的复杂性,这可能不合适。另外,这种确切的方法可能不适合需要大量操作的对象(即具有许多函数的对象),因为所有这些函数对所有jQuery对象都是通用的。有许多方法可以封装我不会在这里介绍的所有内容,但jQuery-ui使用它们的小部件来完成此操作,而且我正在尝试在我创建的库中另一个替代方案。

但是,拉回来一点,我首先建议使用jQuery的唯一原因是您的Filter对象似乎与DOM密切相关。它将事件绑定到DOM,它基于用户交互来修改DOM,基本上它似乎生活在DOM中,所以使用基于DOM的东西,即jQuery。