如何在 VueJs 中再次加载(重新加载)组件或销毁它并再次加载?

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

我在 VueJs 中有一个组件,例如 Aplayer(或任何其他组件),用于播放音频和管理播放列表。

现在我需要在不改变路由的情况下改变播放列表时重新加载它。有什么方法可以重新加载组件或销毁它然后立即加载它?

我想在this组件播放音乐的时候改变播放列表,但是有时会播放之前播放列表的音乐,不知道为什么。

HTML 细分:

<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 细分:

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]
    }
  }
}

您的更改未被采纳的原因是您(或播放器组件) 没有正确利用 Vue 的反应系统。您应该使用 the appropriate array mutation method so that array reactivity 进行维护。 Vue 不会拾取直接对数组元素所做的更改

意思是,当您执行以下操作时:

this.myArray[1] = "some new value";

Vue 将不会采用这些更改。


在Vue中操作数组的正确方法

使用您的 onEnd 方法,尝试将代码更改为此....

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);
}

编辑:

我看了一下 aplayer 组件代码。我的答案之所以有效,是因为它采用了您提供的 :list,以及 computes a new propertymusicList

(这里是代码,以备日后修改)

musicList () {
  return this.list
}

我发现 Vue 文档 this excerpt 对理解这里发生的事情很有帮助...

computed properties are cached based on their reactive dependencies. A computed property will only re-evaluate when some of its reactive dependencies have changed.

因此,当您更改数组而不使用适当的方法来保持反应性,然后将其传递给 a-player 组件时,计算的 属性 不会更新。因此,您的旧播放列表仍然存在 :)

最简单的技巧,只需使用 v-if:

<aplayer v-if='loaded' />

脚本

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
    }
  }
}