6

我是一名中级前端 JS 开发人员,我正在尝试 Chris Coyyer在这里概述的模块模式。

但是当我在设置中存储一个 jQuery 选择器时,我无法使用它来触发点击事件。请参阅下面的代码和我的评论......非常感谢任何帮助!

var s,
TestWidget = {
  settings: {
    testButton: $("#testing")
  },
  init: function() {
    s = this.settings;
    this.bindUIActions();
  },
  bindUIActions: function() {
    console.log(s.testButton); // This works: [context: document, selector: "#testing", constructor: function, init: function, selector: ""…]

    //This doesn't work - why?????
    s.testButton.click(function() {
        //Why isn't this triggered?
        alert('testButton clicked');
    });

    /*This works, obviously:
    $('#testing').click(function() {
        alert('testButton clicked');
    });
    */

  }
};
$(document).ready(function() {
    TestWidget.init();
});
4

1 回答 1

10

问题是你$("#testing")在 DOM 准备好之前进行了初始化,所以这个 jQuery 对象是空的。

一个简单的解决方案是将所有代码放入就绪回调中。

另一种是更换

  settings: {
    testButton: $("#testing")
  },
  init: function() {
    s = this.settings;
    this.bindUIActions();
  },

  settings: {
  },
  init: function() {
    s = this.settings;
    s.testButton = $("#testing");
    this.bindUIActions();
  },

但是很难理解为什么要为这么简单的事情使用这么多代码。您可能在这里过度使用了该模式,并且它并不是很干净,因为您有两个全局变量s,而TestWidget一个已经很多了。

这是您的代码的一个细微变化,在我看来,它会更干净,同时仍然使用模块(IIFE 变体):

TestWidget = (function(){
    var settings = {};
    return {
        init: function() {
            settings.testButton = $("#testing");
            this.bindUIActions();
        },
        bindUIActions: function() {
            console.log(settings.testButton);
            settings.testButton.click(function() {
                alert('testButton clicked');
            });
        }
    }

})();
$(document).ready(function() {
    TestWidget.init();
});

settings保存在闭包中,不会在全局命名空间中泄漏。请注意,如果您不对模块进行更多操作,即使此版本也没有意义。

于 2013-07-19T15:42:56.657 回答