Reputation: 4392
I have a component in VueJs such as Aplayer(or any other components) for playing audio and managing playlist on it.
Now I need to reload it when I change the playlist without changing the routes. is there any way to reload a component or destroy it then load it immediately?
I want to change the playlist of this component while it playing music, but sometimes it plays the music of the previous playlist and I don't know why.
HTML segment:
<aplayer autoplay
ref="remote"
:music="music_list[0]"
:list="music_list"
:float="float"
:mutex="mutex"
repeat="list"
:mini="mini"
preload="auto"
@ended="onEnd"
@loadstart="playCMD"
@playing="onStart"
:listFolded="listFolded"
:controls="controls"
:muted.sync="muted"
:volume.sync="volume"
slot="display"
/>
JavaScript segment:
export default {
components: {
Aplayer
},
data: () => ({
float: false,
autoplay: true,
mutex: true,
muted: false,
volume: 0.8,
mini: false,
listFolded: false,
controls: true,
music_list: [..]
}),
methods: {
onEnd: function () {
// Doing a series of jobs that leads to raising an event then
this.music_list = [new music list after event trigger]
}
}
}
Upvotes: 1
Views: 3376
Reputation: 2865
The reason that your changes are not being picked up is because you (or the player component) are not utilizing Vue's reactivity system properly. You should be using the appropriate array mutation method so that array reactivity is maintained. Vue will not pickup changes made directly to array elements.
Meaning, when you do something like:
this.myArray[1] = "some new value";
Those changes will not be picked up by Vue.
Using your onEnd
method, Try changing the code to this....
onEnd: function () {
// Assumption: resultOfSomeJob is an array of songs for the playlist
// Clear our playlist
this.music_list = [];
// Push elements to our music_list using the Vue array method "push"
this.music_list.push(...resultOfSomeJob);
}
I took a look at the aplayer
component code. The reason my answer works is because it takes the :list
that you give it, and computes a new property, musicList
.
(Here is the code in case it changes in the future)
musicList () {
return this.list
}
I found this excerpt from the Vue docs pretty helpful in understanding what's going on here...
computed properties are cached based on their reactive dependencies. A computed property will only re-evaluate when some of its reactive dependencies have changed.
So, when you change your array without using the proper methods to maintain reactivity and then it is passed to the a-player
component, the computed property is not updated. Thus, your old playlist remains :)
Upvotes: 1
Reputation: 16513
Simplest hack, just use v-if
:
<aplayer v-if='loaded' />
script
export default {
components: { Aplayer },
data: () => ({
loaded: true,
}),
methods: {
onEnd: function () {
// when you want to reload the component just make `loaded = false`
this.loaded = false;
// load agin with `setTimeout` or promise
// or with your logic - whenever the component is ready to show
setTimeout(() => {
this.loaded = true
}, 500); // delay in ms
}
}
}
Upvotes: 1