2012-06-11 83 views
0

我想在JavaScript中创建几个自定义对象,我不确定我是否正确地处理事情。如何让自定义对象侦听子自定义对象的事件?

我有两个对象:'UserInterface'和'VolumeSlider'。直到刚才这两个对象是独立的,但通过方法耦合。我决定UserInterface应该'​​拥有'一个VolumeSlider。

所以:

UserInterface = { 
    _volumeSlider: null, 

    initialize: function() { 
     this._volumeSlider = VolumeSlider; //TODO: Should this be a new volumeSlider(); 
     this._volumeSlider.initialize(); 

     //I want to setup a listener for VolumeSlider's change-volume events here. 
    } 
} 

VolumeSlider = { 
    _volumeSlider: null, 

    initialize: function() { 
     this._volumeSlider = $('#VolumeSlider'); 
     var self = this; 
     this._volumeSlider.slider({ 
      orientation: 'horizontal', 
      max: 100, 
      min: 0, 
      value: 0, 
      slide: function (e, ui) { 
       self.passVolumeToPlayer(ui.value); 
      }, 
      change: function (e, ui) { 
       self.passVolumeToPlayer(ui.value); 
      } 
     }); 
    }, 

    passVolumeToPlayer: function (volume) { 
     if (volume != 0) 
      UserInterface.updateMuteButton(volume); 
     else 
      UserInterface.updateMuteButton('Muted'); 
    } 
} 

的问题有两个方面:

  • 这是一种正常的方式来创建我的对象和设置的孩子吗?
  • 我想UserInterface能够响应VolumeSlider._volumeSlider的变化和幻灯片事件,而不必明确告诉。我该如何去做到这一点?

回答

1

这是一个正确的方式来创建我的对象和设置孩子?

如果它的工作原理,这是“正常的” :)
但在所有的严重性,也有实际的方法来设置这样的事情了一个无限的数量。取决于你的需求。

但是,我会说,如果需要超过1个滑块,则代码将变得笨重。


我想的UserInterface能够以VolumeSlider._volumeSlider的变化和幻灯片事件作出反应,而不必被明确告知。我该如何去做到这一点?

我可能只是跳过VolumeSlider对象。它不是构造函数(“类”),所以它是一次性使用并且硬编码到#VolumeSlider元素。此外,从您的代码,它并不真所有这些。似乎只是一个中间人。

这里有一个选择:

UserInterface = { 
    initialize: function() { 
    // Internal function to create a horizontal 0-100 slider 
    // Takes a selector, and a function that will receive the 
    // value of the slider 
    function buildSlider(selector, callback) { 
     var element = $(selector); 
     var handler = function (event, ui) { callback(ui.value); }; 
     element.slider({ 
     orientation: 'horizontal', 
     max: 100, 
     min: 0, 
     value: 0, 
     slide: handler, 
     change: handler 
     }); 
     return element; 
    } 

    // We probably want to bind the scope of setVolume, so use $.proxy 
    this.volumeSlider = buildSlider("#VolumeSlider", $.proxy(this.setVolume, this)); 

    // Want more sliders? Just add them 
    // this.speedSlider = buildSlider("#SpeedSlider", $.proxy(this.setSpeed, this)); 
    // this.balanceSlider = buildSlider("#BalanceSlider", $.proxy(this.setBalance, this)); 
    // etc... 
    }, 

    setVolume: function (value) { 
    if(value != 0) { 
     // not muted 
    } else { 
     // muted 
    } 
    } 
} 

有了这个,你可以想见,创建滑块的X号你需要的任何目的。并没有单独使用的一个对象;一切都在UserInterface对象中处理。

当然,这本身可能不是最好的想法,但为了这个简单的目的,它是可以的。但是,您可能想要将buildSlider解压缩为更一般的UIElements对象。它可以有方法,如buildSliderbuildButton

或者,你可以去了“非侵入式JavaScript”往来港澳和有特殊的类名和data-属性,将宣布如何以及在何处元素适合在UI中。例如

<div id="volumeSlider" class="ui-element" data-role="slider" data-action="setVolume">...

可以与所有使用$(".ui-element").each ...之后,它的属性可以被解析的其他UI元素一起被发现意味着它应该被拍成名为“volumeSlider”滑块,其滑动/变化事件应该呼叫setVolume ... Et cetera。

再说一遍,有很多种方法可以解决它。

1

我不认为你的原始结构会变得笨拙。在这种情况下,JavaScript的内置数据结构将有所帮助。

如果你需要一个以上的音量滑块,只要该位_volumeSlider: null,改变_volumeSliders: [],

如果通过参考需要滑块,初始化_volumeSlidersdict。然后通过_volumeSliders[selector]来引用它们,并且你已经得到了你的对象。

除了向上传递值的函数之外,还向下发送对父实例的引用。那么你可以写,parent.volume = value。作为一个经验法则,我严格遵守坚实的逻辑层次结构。永远不要改变你的架构,只需创建范围引用。在这种情况下,引用父范围。我不会使用第一个回答者的方法,因为我可能不得不四处寻找正在创建的对象的来源。

第一个回答者有一些好主意。您可能会注意到某些重复出现的模式,例如设置一个jQuery元素引用。我通常会等待,直到我注意到这些重复的模式,然后DRY与抽象,例如。一个基类,如Flambino所建议的,例如UIElement