Ali Hallaji
Ali Hallaji

Reputation: 4392

How to load again(reload) component in VueJs or destroy it and load again?

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

Answers (2)

Evan Bechtol
Evan Bechtol

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.


The correct way to manipulate an array in 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);
}

Edit:

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

Syed
Syed

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

Related Questions