zl程序教程

您现在的位置是:首页 >  前端

当前栏目

vue系列:vue使用腾讯云播放器TCPlayer踩坑cannot read propeerty ‘nodeName‘of null

Vue腾讯 系列 of Cannot null Read 播放器
2023-09-27 14:27:09 时间

需求

列表页进入详情页,详情页有视频播放功能。
进入详情页调接口异步获取appid和fileid,然后初始化播放器。

bug

视频播放器在有异步的情况下无法正常初始化。

文件引入顺序

在 vue 中引入腾讯视频, 原则是 先加载腾讯视频代码 → 加载 dom → 加载视频初始化代码,

本次测试代码 header 引入 腾讯视频播放器 js,body 底部是 vue 项目的 js 代码。

bug重现

我把功能模拟到最简了,用 setTimeOut 模拟异步,报错如下图

<template>
  <div id="detail">
    <div class="detail-title">12344556</div>
    <div class="detail-video">
      <video width="414"
            :id="tcPlayerId"
            height="270"
            class="tc-video-container"
            playsinline
            webkit-playinline
            x5-playinline>
      </video>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Detail',
  data () {
    return {
      tcPlayerId: 'tcPlayer' + Date.now(),
      player: null
    }
  },
  mounted () {
    let self = this
    this.$nextTick(() => {
      setTimeout(() => {
        let videoFileid = '5285890797533824165'
        let videoAppid = 'xxxxxxxx'
        self.getVideoLang(videoFileid, videoAppid)
      }, 400)
      // let videoFileid = '5285890797533824165'
      // let videoAppid = 'xxxxxxxx'
      // self.getVideoLang(videoFileid, videoAppid)
    })
  },
  methods: {
    // 初始化腾讯云播放器
    getVideoLang (fileID, appID) {
      const playerParam = {
        fileID: fileID,
        appID: appID
      }
      this.player = window.TCPlayer(this.tcPlayerId, playerParam)
    }
  }
}
</script>

在这里插入图片描述

解决办法

解决的关键点有两点:

  1. video 上要用 v-if 判断是否已经加载上了 fileid 和 appid,只有加载上这两个 id 之后再渲染 dom,这样才不至于出现 dom 加载了但是找不到这俩 id
  2. 初始化视频的时候需要加上 this.$nextTick 以确保 dom 节点加载完成
<template>
  <div id="detail">
    <div class="detail-title">12344556</div>
    <div class="detail-video">
      <video width="414"
            v-if="videoFileid"
            :id="tcPlayerId"
            height="270"
            class="tc-video-container"
            playsinline
            webkit-playinline
            x5-playinline>
      </video>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Detail',
  data () {
    return {
      tcPlayerId: 'tcPlayer' + Date.now(),
      player: null,
      videoFileid: '',
      videoAppid: ''
    }
  },
  mounted () {
    let self = this
    setTimeout(() => {
      self.videoFileid = '5285890797533824165'
      self.videoAppid = 'xxxxxxx'
      self.$nextTick(() => {
        self.getVideoLang(self.videoFileid, self.videoAppid)
      })
    }, 2000)
  },
  methods: {
    // 初始化腾讯云播放器
    getVideoLang (fileID, appID) {
      const playerParam = {
        fileID: fileID,
        appID: appID
      }
      this.player = window.TCPlayer(this.tcPlayerId, playerParam)
    }
  }
}
</script>

再次进来播放器无法加载的问题

这里动态绑定播放器 id,可以解决返回再次进来播放器无法加载的问题,还有一种解决方案就是:

beforeDestroy () {
  this.player.dispose()
}

生命周期组件销毁的时候把播放器也销毁掉,这是腾讯云播放器的 api