包装JavaScript对象内的DOM元素

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

<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
};

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


您可能对Dojo的小部件库Dijit感兴趣 - 如果我能正确理解您的问题,它基本上可以解决您所问的问题以及更多问题。

在Dijit中,一个小部件本质上封装了一个DOM节点,其内容,任何定义其行为的JavaScript,以及(单独导入)CSS来设计其外观。

小部件有自己的生命周期,注册表和事件(包括许多简单地映射到小部件内的节点上的DOM事件,例如myWidget.onClick可以有效地调用myWidget.domNode.onclick )。

小部件可以(但不必)将其初始内容定义在单独的HTML模板文件中,通过该文件也可以将模板内的节点上的事件绑定到小部件方法,并且可以在小部件上设置属性节点在模板中。

我几乎没有在这里抓到表面。 如果您想了解更多信息,可以从这些参考页面开始:

  • http://dojotoolkit.org/reference-guide/dijit/info.html
  • http://dojotoolkit.org/reference-guide/dijit/_Widget.html(所有小部件扩展的基础)
  • http://dojotoolkit.org/reference-guide/dijit/_Templated.html(RE HTML模板)
  • http://dojotoolkit.org/reference-guide/quickstart/writingWidgets.html(开始编写自己的小部件时的有用信息)
  • http://dojotoolkit.org/reference-guide/dijit/(有关更多信息)
  • 所有人都说,我不知道你最终的目标是什么,也许这对你的目的来说很有意思(考虑到我把一个其他的图书馆扔给你),但是认为它可能会激起你的兴趣。


    继续我对这个问题的评论,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。

    链接地址: http://www.djcxy.com/p/4419.html

    上一篇: Wrapping a DOM element inside a JavaScript object

    下一篇: jqGrid filter or search by date not working client side