vue2中的引用问题是真多,这不 一不小心又入坑了
问题复现:
<template>
<div class="right-warp">
<div class="video-warp">
<BFileVideo
ref="videoPlayer"
:url="url"
:defaultOptions="defaultOptions"
:videoTypes="['application/x-mpegURL', 'm3u8']"
/>
</div>
</div>
</template>
在这段代码中 我封装了一个videojs的组件,外部可以通过配置项来动态修改里面的属性,但是这段代码也是被包裹在其它的父组件中的。
在BFileVideo中有这么一段计算函数:
computed:{
videoOptions() {
if (!this.url) {
return {};
}
const suffix = this.url.substring(this.url.lastIndexOf('.') + 1);
if (!this.videoTypes.find(item => item.indexOf(suffix) > -1)) {
return {};
}
const sources = this.videoTypes.map(item => ({
type: item,
src: this.url
}));
return {
...videojs其它配置
...this.defaultOptions
}
}
}
在BFileVideo的组件中 计算了videoOptions,这个会直接赋值给videojs的组件,这里其中我把videoTypes也放到这个计算属性中了,众所周知,vue中的计算属性只要里面的随便哪个变量发生变化,这个计算属性就会重新更新计算。
问题来了 当我外层组件有发生更新的时候,这个计算属性就会重新计算,导致前端报错
VIDEOJS: ERROR: TypeError: Cannot read properties of null (reading 'autoplay')
at Html5.<computed> [as autoplay] (video.cjs.js:18896:20)
at MasterPlaylistController.handleSourceOpen_ (master-playlist-controller.js:859:22)
at data.dispatcher (video.cjs.js:1967:31)
at trigger (video.cjs.js:2099:25)
at EventTarget.trigger (video.cjs.js:2593:3)
这个是videojs抛出来的,意思大概就是找不到videojs对象 无法播放,因为我在上面不断的重新计算了videoOptions的属性,导致videojs里的对象不断的变化 从而引起报错了。
解决方案:
其实很简单:
<template>
<div class="right-warp">
<div class="video-warp">
<BFileVideo
ref="videoPlayer"
:url="url"
:defaultOptions="defaultOptions"
:videoTypes="videoTypes"
/>
</div>
</div>
</template>
<scropt>
export default{
data(){
return {
videoTypes:['application/x-mpegURL', 'm3u8']
}
}
}
</script>
把videoTypes放到data里包裹起来,而不是直接绑定到属性上。
这样这个属性就不会在父组件更新的时候发生变化了,videoTypes也不会引起BfileVideo的计算属性的重新计算了