今天为了在vue中为了视频加载失败后显示图片搞了半天,网上说的方法都试过了,但是都无法解决,后来不得不换个方式解决了。因此把几种方式总结一下,最后附上我的解决办法。
1、目的及正常解决方式的代码
当视频加载失败后,用一张图片代替视频,提示用户视频加载失败。下面的是正常的处理方式,但是我在使用过程中却遇到了问题。
<video
v-if="videoItem.status===true"
class="videoDiv-video"
preload="meta"
controls="controls"
:error="videoLoadError(videoItem)"
:src="videoItem.fileUrl" >
</video>
<img v-else src="../../../assets/img/videoErr.png">
videoLoadError (videoItem) {
videoItem.status = false;
}
2、遇到的问题
因为video加载有可能失败,因为使用videoLoadError方法处理视频加载失败的情况,结果却发现无论视频是否加载成功都会触发error事件对应的videoLoadError方法,后来又换了onload、onemptied等一系列方法,甚至click都试过了,结果发现依然会立刻触发。
源代码。
3、解决方案
3.1、重新设置onerror方法
依然用:error来绑定事件,实际上这里用别的事件,什么click、onload也一样,但是为了可读性和控制台不报错就毅然使用error事件。
先不给video设置src属性(因为之后会重新请求,现在不需要请求,减少向服务器的请求次数),然后给videoItem的fileName值作为每个video的id,并在idvideoLoadError传入videoItem对象,在触发了videoLoadError方法之后,根据id找到对应的video,然后重新设置onerror对应的方法。
<video
v-if="videoItem.status===true"
class="videoDiv-video"
preload="meta"
controls="controls"
:id="videoItem.fileName"
:error="videoLoadError(videoItem)">
</video>
<img v-else src="../../../assets/img/videoErr.png">
videoLoadError (videoItem) {
// 延时再次设置onerror事件
setTimeout(() => {
let video = document.getElementById(videoItem.fileName);
video.onerror = function () { // 这里要用onerror
videoItem.status = false;
video.src = videoItem.fileUrl;
video.onerror = null; // 避免加载失败后陷入死循环
}
video.src = videoItem.fileUrl;
}, 100);
}
3.2、 prevent修饰符解决
在error事件上后面添加修饰符prevent即可解决,后来又遇到了一个另一个click事件问题,解决后又回过头在这个问题上进行了尝试,也可以解决这个问题。
<video
v-if="videoItem.status===true"
class="videoDiv-video"
preload="meta"
controls="controls"
:id="videoItem.fileName"
v-on:error.prevent="videoLoadError(videoItem)"
:src="videoItem.fileUrl">
</video>
videoLoadError (videoItem) {
videoItem.status = false;
}