2016-04-25 84 views
0

我对Ember JS很新,我甚至不得不承认这是我第一个使用的框架。Ember JS - 组件vs.工厂

好吧。我正面临设计问题。我想制作一个音频网络应用程序,它总是需要能够播放音频,因此我想制作一个AudioPlayer单身人士,这个单身人士可以在应用程序的整个生命周期中使用。

据Ember的上Dependency Injection文档我可以只注册一个工厂,在默认情况下被注册为单身,我可以通过所有的时间访问:

applicationInstance.lookup('audio:player'); // For example 

这似乎是一个想法,但我也需要一个音频播放器的接口,带有播放,暂停和停止等旋钮; HTML是。那可能吗?为工厂做一个“观点”?

我看到的第二个可能性是使一个audio-player组件,但与组件我不得不放弃单身了,我真的只希望自己的网站,这也将是AudioContext的船东,只是一个audioplayer ,每个网站只需要一次。

所以。我该怎么办?我应该去工厂还是与模型?


PS:我想认为我需要一个控制器,但我已经灰烬JS指南,这是很快就被弃用读取。

+1

一个选项是你仍然可以使用提供UI的组件,并且这个组件可以使用包含所有核心功能的audioPlayer服务,并且服务默认为singleton。(https://guides.emberjs.com/ v2.5.0/applications/services /) –

回答

2

我很快为您实施了一些东西,它扩展了@Deewendra的评论。您会看到该应用程序由两个前述部分组成。

在服务目录

export default Ember.Service.extend({ 
    ids: [0,1,2,3,4,5,6,7,8,9,10], 
    songs: Ember.computed('ids',function(){ 
    return this.get('ids').map(id => { 
     return { id: id, title: `Awesome Song ${id}`} 
    }) 
    }), 
    currentlyPlaying: '', 
    currentIndex: 0, 
    currentStatus: 'stopped', 

    start() { 
    this.setSongByIndex(); 
    this.set('currentStatus','playing'); 
    }, 
    stop(){ 
    this.set('currentStatus','stopped'); 
    }, 
    nextSong() { 
    let maxIndex = this.get('ids.length') - 1; 
    let currentIndex = this.get('currentIndex'); 
    let nextIndex = currentIndex + 1; 

    if (nextIndex > maxIndex) { 
     this.stop(); 
    } else { 
     this.set('currentIndex',nextIndex); 
     this.setSongByIndex(); 
    } 
    }, 
    previousSong() { 
    let maxIndex = this.get('ids.length') - 1; 
    let currentIndex = this.get('currentIndex'); 
    let prevIndex = currentIndex - 1; 

    if (prevIndex < 0) { 
     this.stop(); 
    } else { 
     this.set('currentIndex',prevIndex); 
     this.setSongByIndex(); 
    } 
    }, 
    setSongByIndex() { 
    const songs = this.get('songs'); 
    const currentIndex = this.get('currentIndex'); 
    this.set('currentlyPlaying',songs[currentIndex]); 
    } 
}); 

其是通过使用Ember.inject.service()方法连接到服务的音频播放器组件

// components/audio-player.js 
export default Ember.Component.extend({ 
    audioPlayer: Ember.inject.service('audio-player'), 
    actions: { 
    start() { 
     this.get('audioPlayer').start(); 
    }, 
    stop() { 
     this.get('audioPlayer').stop(); 
    }, 
    next(){ 
     this.get('audioPlayer').nextSong(); 
    }, 
    previous(){ 
     this.get('audioPlayer').previousSong(); 
    } 
    } 
}); 

// templates/components/audio-player 
Song Title: {{audioPlayer.currentlyPlaying.title}} <br/> 
Audio Player Status: {{audioPlayer.currentStatus}} <br/> 
<button {{action 'start'}}>Start</button> | 
<button {{action 'next'}}>Next</button> | 
<button {{action 'previous'}}>Previous</button> | 
<button {{action 'stop'}}>Stop</button> | 

的音频播放器的服务。如你所见,玩家的“状态”存在于服务中,并且组件通过html/handlebars模板与其交互,并与一个与该模板名称相当的JavaScript文件相结合,这将会处理“视图”(模板)和“状态”(服务)之间的交互。

这是一个twiddle点击进去,并进行实验。

我不确定你的经验是关于“框架”之外的编程方面的,关于网络技术等方面的问题,并且提交过这个问题想过两次,但我认为它应该比它受到的伤害更大。

+0

我还没有真正意识到服务。非常感谢你! – Tomasito665

+0

我建议在'init'方法中初始化属性,特别是数组和对象。在这种情况下,这不是一个问题,因为服务是单身人士,但这是一个很好的做法。 – locks