Vue3使用VideoJS实现播放列表出现Maximum call stack size exceeded错误
问题原因及修复方案
根本原因:组件命名冲突导致无限递归渲染
你出现Maximum call stack size exceeded报错的核心原因是多个组件的name属性和注册的子组件重名,触发了Vue的递归渲染逻辑,无限循环导致栈溢出:
- 引入VideoOne的about页面自身
name属性设置为VideoOne,同时又注册了同名的子组件VideoOne,渲染时会无限把自身作为子组件加载 - VideoOne组件自身
name属性设置为vidPlayer,同时又注册了同名的子组件vid-player(对应你引入的Player组件,而Player组件自身name也为vidPlayer),触发第二层递归渲染
次要问题:Player组件初始化参数错误
你的Player组件中playerOptions.sources读取了this.playerdata.source,但你传入的playerdata中仅包含playlist字段,没有source字段,会导致初始src为undefined,触发模板中的v-if="playerOptions.sources[0].src"判断为假,组件无法正常渲染。
修复方案
步骤1:修改所有冲突的组件名,保证每个组件name唯一
- 修改about页的
name属性,避免和子组件重名:
<template> <div class="about"> <h1>This is an about page</h1> <VideoOne></VideoOne> </div> </template> <script> import VideoOne from '@/components/VideoOne'; export default { components: { VideoOne }, name: "AboutPage" // 原来的VideoOne改成唯一名称 } </script>
- 修改VideoOne组件的
name属性,避免和子组件重名:
<template> <div class="mt-2"> <vid-player ref="videoPlayer" :playerdata="playerdata"></vid-player> </div> </template> <script> import vidPlayer from "../components/Player"; export default { components: { 'vid-player': vidPlayer }, name: "VideoOneComponent", // 原来的vidPlayer改成唯一名称 data() { return { playerdata: { autoplay: false, playlist: [{ sources: [{ src: 'http://media.w3.org/2010/05/bunny/trailer.mp4', type: 'video/mp4' }], poster: 'http://media.w3.org/2010/05/bunny/poster.png' }, { sources: [{ src: 'http://vjs.zencdn.net/v/oceans.mp4', type: 'video/mp4' }], poster: 'http://www.videojs.com/img/poster.jpg' }, { sources: [{ src: 'http://media.w3.org/2010/05/bunny/movie.mp4', type: 'video/mp4' }], poster: 'http://media.w3.org/2010/05/bunny/poster.png' }, { sources: [{ src: 'http://media.w3.org/2010/05/video/movie_300.mp4', type: 'video/mp4' }], poster: 'http://media.w3.org/2010/05/video/poster.png' }], }, } }, computed: { player() { return this.$refs.videoPlayer.player } }, } </script>
步骤2:修复Player组件的初始化参数
把初始的sources设置为播放列表第一个视频的地址,或者直接修改v-if的判断逻辑:
<template> <div v-if="playerdata.playlist && playerdata.playlist.length"> <video-player class="video-player-box" ref="videoPlayer" :options="playerOptions" :playsinline="true" @ready="playerReadied"> </video-player> </div> </template> <script> import { videojs } from "vue-video-player"; import playlistMaker from "videojs-playlist/src/playlist-maker"; const plugin = function(list, item) { playlistMaker(this, list, item); }; videojs.registerPlugin("playlist", plugin); export default { name: "vid-player", props: ["playerdata"], data() { return { playerOptions: { language: 'en', controls: true, preload: 'auto', fluid: true, playbackRates: [0.2, 0.5, 1, 1.5, 2,3,4], sources: this.playerdata.playlist[0].sources, // 取播放列表第一个的资源 }, } }, methods: { // player is ready playerReadied(player) { this.player = player; console.log('the player is readied', player) player.playlist(this.playerdata.playlist); player.playlist.autoadvance(5); }, } }; </script>
修改完成后重新启动项目即可正常渲染,栈溢出报错也会消失。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

