【vue】elementUI报错:_self.$scopedSlots.default is not a function

Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。

这样也不总是符合实际需求,所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key 属性即可。见详情

错误代码

<!-- 代码块1 -->
<el-table-column label="授信申请状态" v-if="type">
  <template slot-scope="scope">{{ scope.row.data2 | format }}</template>
</el-table-column>
<!-- 代码块2 -->
<el-table-column prop="data1" label="联系人手机" v-else></el-table-column>

报错分析

如果优先显示代码块1,然后改变type值,显示代码块2,这时Vue为了快速渲染页面,会优先拿代码1的代码渲染到代码块2的位置,但是代码块2并没有定义 slot-scope ,这时就会报标题错误。

解决方案

  1. 给使用 v-ifv-else 的地方加上 key
  2. v-ifv-else 换成 v-show

个人博客:午后南杂

<template> <div class="video-play-box" style="width: 100%; height: 100%"> <div id="video-wrap-player" v-if="mediaUri"> <video-player class="video-player vjs-custom-skin" ref="videoPlayer" :options="playerOptions" :playsinline="true" @ready="onPlayerReady" @play="onPlayerPlay" @timeupdate="onPlayerTimeupdate" @pause="onPlayerPause" @ended="onPlayerEnded"> </video-player> </div> <div class="watermark">{{ waterText }}</div> </div> </template> <script> import { getCourseLessonsDetail, updateCourseLearning } from &#39;@/api/course&#39; export default { name: &#39;videoboPlayer&#39;, props: [&#39;courseId&#39;, &#39;isDrag&#39;, &#39;doubleSpeed&#39;, &#39;from&#39;], data() { return { coursewareId: this.$route.query.coursewareId, stageId: this.$route.query.stageId, // 阶段ID isPaused: &#39;&#39;, // 视频暂停 canDrag: false, // 是否可拖动 只有首次不可拖动 currentTime: 0, // 当前学习位置 nowCurrentTime: &#39;&#39;, // 视频当前学习位置 learnProgress: 0, // 学习进度 TimingUpdateProgress: {}, // 定时更新进度计时器 videoTotalLength: 0, // 视频总时长 player: null, // 视频对象 isEnded: false, // 是否触发视频end事件 isUpdateing: false, // 更新课件进度接口请求中 waterText: &#39;&#39;, // 水印文字 sourceId: &#39;&#39;, // 来源id nextCourseware: {}, // 下一课件的内容 lessonData: {}, mediaUri: &#39;&#39;, // 修复:添加isStart到data中 isStart: false, // 修复:添加playerOptions到data中 playerOptions: {}, } }, components: {}, computed: {}, watch: { $route: function () { if (!this.isStart) { this.getVideoDetail() } }, // 视频暂停更新进度 isPaused(val) { if (val) { this.updateLearningTime(this.currentTime) } }, }, mounted() { let _self = this // 水印 _self.waterText = window.localStorage.getItem(&#39;companyName&#39;) if (this.from == &#39;train&#39;) { this.sourceId = this.$route.query.trainId } else { this.sourceId = this.courseId } // 禁用鼠标右键 document.querySelector(&#39;.course-learn-body&#39;).onselectstart = document.querySelector(&#39;.course-learn-body&#39;).oncontextmenu = function () { return false } function KeyDown() { // 屏蔽鼠标右键、Ctrl+n、shift+F10、F5刷新、退格键 if (window.event.altKey && (window.event.keyCode == 37 || window.event.keyCode == 39)) { // 屏蔽 Alt+ 方向键 → event.returnValue = false } } document.onkeydown = KeyDown _self.getVideoDetail() }, beforeDestroy() { var _self = this _self.updateLearningTime(_self.currentTime) // 清除视频30秒记录定时器 clearInterval(_self.TimingUpdateProgress) }, destroyed() { }, methods: { onPlayerReady(player) { let _self = this _self.isStart = false console.log(&#39;Player is ready!&#39;, player) // 保存播放器实例以便后续使用 _self.player = player $(&#39;.vjs-control-bar&#39;).children().addClass(&#39;needsclick&#39;) // 修复:为播放器添加重播事件监听 player.on(&#39;replay&#39;, function () { console.log(&#39;重播事件触发&#39;) _self.resetPlayState() }) if (_self.isDrag == &#39;close&#39; && !_self.canDrag) { // 禁止拖动 document.querySelector(&#39;.vjs-progress-control&#39;).style.pointerEvents = &#39;none&#39; console.log(&#39;禁止拖动&#39;) } else { document.querySelector(&#39;.vjs-progress-control&#39;).style.pointerEvents = &#39;auto&#39; console.log(&#39;可以拖动&#39;) } // 设置初始播放位置 player.currentTime(_self.currentTime) }, /** * 修复:重置播放状态的方法 */ resetPlayState() { console.log(&#39;重置播放状态&#39;) this.isEnded = false this.isPaused = false // 重置当前时间为0,从头开始播放 this.currentTime = 0 // 如果有播放器实例,重置播放器 if (this.player) { this.player.currentTime(0) } }, onPlayerPlay(player) { console.log(&#39;开始播放&#39;) // 修复:检查是否是播放结束后重新播放 if (this.isEnded) { this.resetPlayState() } // 设置初始播放位置 player.currentTime(this.currentTime) this.isPaused = false this.isEnded = false // 定时同步进度(30s一次) this.TimingUpdateProgress = setInterval(() => { this.updateLearningTime(this.currentTime) }, 30000) }, onPlayerTimeupdate(player) { console.log(&#39;播放中&#39;, this.nowCurrentTime) this.nowCurrentTime = player.currentTime().toFixed(2) this.currentTime = this.nowCurrentTime // 暂停时传递进度 if (this.isPaused) { this.currentTime = this.nowCurrentTime } // 修复:检查是否接近视频结尾,如果是,准备重置状态 const remainingTime = this.videoTotalLength - this.currentTime if (remainingTime < 1 && !this.isEnded) { // 即将结束,准备重置状态 console.log(&#39;视频即将结束,准备重置状态&#39;) } }, onPlayerPause(player) { console.log(&#39;暂停播放&#39;) // 防止拖动产生的pause事件重复发送请求 if (!this.isPaused) { clearInterval(this.TimingUpdateProgress) this.currentTime = player.currentTime().toFixed(2) this.isPaused = true } }, onPlayerEnded(player) { console.log(&#39;视频播放结束&#39;) // 添加isEnded判断,防止重复 if (this.isEnded) { return } // 结束播放时自动推出全屏 if (player.isFullscreen()) { player.exitFullscreen() } clearInterval(this.TimingUpdateProgress) // 播放完毕,设置进度条拖动状态 this.canDrag = true this.isEnded = true this.isPaused = true // 修复:更新最后的学习进度 this.updateLearningTime(this.videoTotalLength) // 修复:监听播放器的重播按钮点击 this.setupReplayListener(player) }, /** * 修复:设置重播监听器 */ setupReplayListener(player) { const _self = this // 监听重播按钮点击(video.js的重播按钮) const replayBtn = player.controlBar.replayControl if (replayBtn) { replayBtn.off(&#39;click&#39;) // 移除之前的监听器 replayBtn.on(&#39;click&#39;, function () { console.log(&#39;重播按钮被点击&#39;) _self.resetPlayState() // 延迟播放以确保状态已重置 setTimeout(() => { player.play() }, 100) }) } // 监听大重播按钮(结束时的重播按钮) const bigPlayButton = player.bigPlayButton if (bigPlayButton) { bigPlayButton.off(&#39;click&#39;) bigPlayButton.on(&#39;click&#39;, function () { console.log(&#39;大播放按钮被点击(可能是重播)&#39;) // 如果当前是结束状态,重置 if (_self.isEnded) { _self.resetPlayState() } }) } }, // 获取视频详情 async getVideoDetail() { let _self = this _self.isStart = true _self.coursewareId = _self.$route.query.coursewareId await getCourseLessonsDetail(_self.coursewareId, { from: _self.from, sourceId: _self.sourceId, courseId: _self.courseId, stageId: _self.stageId ? _self.stageId : _self.courseId, }).then(function (res) { let data = res.data _self.lessonData = data _self.nextCourseware = data.nextCourseware ? data.nextCourseware : {} if (data.convertStatus == 1) { let playbackRates = [] if (_self.doubleSpeed == &#39;open&#39;) { // 开启倍速 playbackRates = [0.5, 1.0, 1.5, 2.0] } else { // 不开启倍速 playbackRates = [] } _self.playerOptions = { //视频url设置,直播流为例 sources: [{ src: _self.lessonData.transCodeUri, //视频文件地址 type: &#39;application/x-mpegURL&#39;, //视频类型,这里可以不写,如果写一定要写对,否则会无法播放 }], playbackRates: playbackRates, fluid: false, autoplay: false, muted: false, inactivityTimeout: 2000, controls: true, responsive: true, // 修复:启用重播控制 replay: true } _self.mediaUri = _self.lessonData.transCodeUri let currentTime = _self.lessonData.progressBar ? _self.lessonData.progressBar : 0 _self.currentTime = currentTime _self.videoTotalLength = _self.lessonData.length _self.learnProgress = _self.lessonData.progress if (_self.learnProgress == 100) { _self.canDrag = true if (Number(_self.currentTime) >= Number(_self.videoTotalLength)) { // 如果已完成,且当前位置大于总时长,定位到0 _self.currentTime = 0 } } else { _self.canDrag = false } _self.currentTime = Math.round(_self.currentTime) // 修复:重置结束状态 _self.isEnded = false } else { // 转码失败 _self.$alert(&#39;视频文件正在转换中,稍后完成后即可查看&#39;, { confirmButtonText: &#39;确定&#39;, callback: (action) => { _self.$router.replace({ name: &#39;knowledgeDetail&#39;, query: { uuid: _self.courseId, }, }) }, }) return false } }).catch((err) => { console.log(err) return }) }, // 更新课件播放时间公共方法(nowPlayTime:当前播放的时间) updateLearningTime(nowPlayTime) { let _self = this if (_self.isUpdateing) { return } _self.isUpdateing = true updateCourseLearning({ coursewareId: _self.coursewareId, progressBar: Number(nowPlayTime).toFixed(2), from: _self.from, sourceId: _self.sourceId, courseId: _self.courseId, stageId: _self.stageId ? _self.stageId : _self.courseId, }).then((res) => { setTimeout(() => { _self.isUpdateing = false }, 1000); if (res.data.progress == &#39;100&#39; && res.data.open) { // 已完成 let lessonInfo = {} if (_self.nextCourseware.uuid) { lessonInfo = { title: _self.nextCourseware.title, courseId: _self.nextCourseware.courseId, uuid: _self.nextCourseware.uuid, coursewareType: _self.nextCourseware.type, } } else { lessonInfo = { uuid: &#39;&#39; } } _self.$emit(&#39;nextLessonPlay&#39;, lessonInfo) } }).catch((err) => { _self.isUpdateing = false }) }, }, } </script> <style src="./video.less" lang="less"></style> <style lang="less"> .vjs-watermark { color: #fff; text-shadow: #000 2px 2px 2px; letter-spacing: 3px; position: relative; width: 200px; display: block; padding-left: 40px; box-sizing: border-box; text-align: center; white-space: nowrap; line-height: 30px; img { width: 30px; height: 30px; position: absolute; top: 0; left: 0; } } /* 修复:确保重播按钮可见 */ .vjs-control-bar .vjs-replay-control { display: block !important; } </style>添加注释,并优化
最新发布
12-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值