Vimeo SDK:初始化后出现未知播放器错误(VueJS)

Vimeo SDK : Unknown Player Error after Initialization (VueJS)

我想使用 Vimeo 播放器在 Vue 网站上显示一堆视频。

为此,我创建了一个为每个视频创建的 VideoPlayer-Component:

<template>

  <div class="video-element__container">
    <div class="video-element__player" ref="player" @click="$emit('shrink')"></div>


    <div class="video-element__play-button" @click="play()"></div>
       
  </div>


</template>

<script>
import Player from '@vimeo/player'

export default {
  name: 'VideoPlayer',
  props: ['isActive', 'id'],
  data () {
    return {
      player: null,
    }
  },
  mounted() {
    this.initPlayer()
  },
  components: {
  },
  methods:
  {
    async play () {
      try {
        await this.player.play()
        this.isPlaying = true
      } catch (e) {
        console.log(e)
      }
    },
    pause() {
      this.player.pause()
      this.isPlaying = false
    },

    initPlayer () {
      let options = {
        url: 'https://vimeo.com/393632283',
        loop: false,
        controls: false,
        muted: true,
      };

      let iframe = this.$refs.player
      this.player = new Player(iframe, options);
    
    }
  }
}
</script>

但是,每当我单击 'play' 时,都会出现以下错误:

Uncaught (in promise) Error: Unknown player. Probably unloaded.
    at readyPromise (player.es.js?84c9:1458)
    at new Promise (<anonymous>)
    at Proxy.ready (player.es.js?84c9:1457)
    at eval (player.es.js?84c9:1311)
    at new Promise (<anonymous>)
    at Proxy.get (player.es.js?84c9:1306)
    at Proxy.getDuration (player.es.js?84c9:2052)
    at Proxy.initPlayer (VideoPlayer.vue?5912:93)
    at Proxy.play (VideoPlayer.vue?5912:53)
    at Object.onClick._cache.<computed>._cache.<computed> (VideoPlayer.vue?5912:17)

然而,当我使用 Vimeo 控件时,它工作得很好。 有人可以在这里看到问题吗?谢谢!

我想你使用的是 Vue 3,因为你的代码对我来说在 Vue 2 上工作得很好,而我在 Vue 3 上遇到了同样的错误。

对于 Vue 3,您需要使用 setup() 方法稍微重构您的代码,如下所示:

<template>
  <div class="video-element__container">
    <div class="video-element__player" ref="playerRef" @click="$emit('shrink')"></div>
    <div class="video-element__play-button" @click="play()"></div>
  </div>
</template>

<script>
import {ref, onMounted} from 'vue';
import Player from '@vimeo/player';

export default {
  name: 'VideoPlayer',
  setup() {
    let player;
    let isPlaying = false;
    const playerRef = ref(null);

    onMounted(() => {
      const options = {
        url: 'https://vimeo.com/393632283',
        loop: false,
        controls: false,
        muted: true,
      };

      player = new Player(playerRef.value, options);
    });

    const play = () => {
      player.play()
          .then(isPlaying = true)
          .catch(e => console.log(e));
    };

    const pause = () => {
      player.pause()
      isPlaying = false
    };

    return {
      player, isPlaying, playerRef, play, pause
    }
  }
}
</script>

上面的代码已经过测试并按预期工作。

您可以查看 Template Refs for more information how to access HTML element inside setup(). Regarding the setup() method itself, please check the Composition API 文档。

此外,还有一些 Vimeo SDK 的 Vue 包装器,例如vue-vimeo-player。如果你愿意,你可以使用它们而不是自己编写。

即使 Triet Doan 的回答现在被接受了,我也不喜欢它。它需要在 Options API 中编写的整个 OP 代码并将其重写为 Composition API 而没有解释为什么需要它...

嗯,根本不需要!事实上,最简单的修复原始代码的方法是在 data() 中注释掉 player: null (如下面的演示所示)

为什么

Vue 的反应性可能有点打扰。使用 Object.defineProperty() (used for reactivity in Vue 2) and proxies 创建的 getters/setters (用于 Vue 3 中的反应性)都可以改变行为,特别是对于复杂数据 types/classes,就像 Vimeo Player 一样。

要解决此类问题,请不要将此类复杂对象放入 data() 或不要将它们包装在 ref()reactive() 中。在大多数情况下,无论如何,您不需要 Vue 模板对此类复杂对象的某些内部状态作出反应....

而是将它们添加到实例中作为 this.player = new ... in mounted hook 或将它们声明为普通变量(没有 ref()reactive())在 setup()

const app = Vue.createApp({
  name: 'VideoPlayer',
  data() {
    return {
      // player: null, <-- THIS LITTLE CHANGE IS NEEDED
    }
  },
  mounted() {
    this.initPlayer()
  },
  methods: {
    async play() {
      try {
        await this.player.play()
        this.isPlaying = true
      } catch (e) {
        console.log(e)
      }
    },
    pause() {
      this.player.pause()
      this.isPlaying = false
    },

    initPlayer() {
      let options = {
        url: 'https://vimeo.com/393632283',
        loop: false,
        controls: false,
        muted: true,
      };

      let element = this.$refs.player
      this.player = new Vimeo.Player(element, options);

    }
  }
})
app.mount('#app')
<script src="https://unpkg.com/vue@3.2.2/dist/vue.global.js"></script>
<script src="https://player.vimeo.com/api/player.js"></script>

<div id="app">
  <div class="video-element__container">
    <div class="video-element__player" ref="player" @click="$emit('shrink')"></div>
    <div class="video-element__play-button" @click="play()"></div>
  </div>
</div>

警告

另一方面,我完全同意使用existing wrapper - vue-vimeo-player. Because it handles some edge cases and more importantly the unloading of the player when the component is destroyed. Without it, you are creating a memory leak in your app

的建议