4👍
✅
Vue only officially supports plain JavaScript objects as reactive data; things like DOM elements and other such objects won’t be and cannot be made reactive.
One way around this is to store just the audioSrc
string and isAudioPlaying
boolean values in the Vuex store and then manage the Audio
object in the root Vue component. You can watch audioSrc
and isAudioPlaying
for changes and then call methods on the Audio
object in response to those changes.
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
audioUrl: null,
isAudioPlaying: false,
},
mutations: {
play(state, url) {
state.audioUrl = url
state.isAudioPlaying = true
},
pause(state) {
state.isAudioPlaying = false
}
}
})
new Vue({
el: '#app',
store,
created() {
this.audio = new Audio()
},
watch: {
'$store.state.audioUrl'(url) {
this.audio.pause()
this.audio.src = url
this.audio.currentTime = 0
this.audio.play()
},
'$store.state.isAudioPlaying'(playing) {
if (playing) {
this.audio.play()
} else {
this.audio.pause()
}
}
},
methods: {
play(url) {
this.$store.commit('play', url)
},
pause() {
this.$store.commit('pause')
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.3/vuex.js"></script>
<div id="app">
<button @click="play('https://upload.wikimedia.org/wikipedia/commons/5/5b/Ludwig_van_Beethoven_-_Symphonie_5_c-moll_-_1._Allegro_con_brio.ogg')">Play Beethoven</button>
<button @click="pause">Pause</button>
<div>audioUrl: {{ $store.state.audioUrl }}</div>
<div>isAudioPlaying: {{ $store.state.isAudioPlaying }}</div>
</div>
Source:stackexchange.com