2012-06-11 85 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