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 的更改和滑动事件,而不必明确告知。我怎样才能做到这一点?
4

2 回答 2

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 个滑块。而且没有单独的一次性VolumeSlider物品;一切都在UserInterface对象中处理。

当然,这本身可能不是最好的主意,但出于这个简单的目的,它是可以的。但是,您可能希望将 提取buildSlider到更一般的UIElements对象中。它可以有类似buildSlider,buildButton等的方法。

或者,您可以采用“Unobtrusive JavaScript”方式并具有特殊的类名和data-属性,它们将声明元素在 UI 中的适合方式和位置。例如

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

可以与所有其他 UI 元素一起使用$(".ui-element").each ...,之后可以解析其属性以表示它应该被制成一个名为“volumeSlider”的滑块,并且它的滑动/更改事件应该调用setVolume......等等。

再一次,有很多很多的方法。

于 2012-06-11T05:35:29.593 回答
1

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

如果您需要多个音量滑块,只需将此位更改_volumeSlider: null,_volumeSliders: [],

如果您需要引用滑块,请初始化_volumeSlidersdict. 然后通过 引用它们_volumeSliders[selector],你就得到了你的对象。

代替向上传递值的函数,向下发送对父实例的引用。然后你可以写,parent.volume = value.

作为一个经验法则,我严格遵守一个坚实的、合乎逻辑的、层次结构的结构。永远不要改变你的架构,只需创建范围引用。在这种情况下,是对父作用域的引用。我不会使用第一个回答者的方法,因为我可能不得不四处寻找正在创建的对象的来源。

第一个回答者有一些好主意。您可能会注意到某些重复的模式,例如设置 jQuery 元素引用。我通常会等到我注意到这些重复的模式,然后用一个抽象来干掉它,例如一个基类,就像Flambino建议的那样,例如UIElement.

于 2012-06-11T06:51:47.457 回答