效果:
知识抢先看:
动态创建节点指的是通过 JavaScript 操作 DOM 来生成 HTML 元素并插入到页面中
document.createElement
: 创建新的 HTML 元素节点。// 创建一个 <div> 元素 const div = document.createElement('div'); // 设置其属性 div.id = 'myDiv'; div.className = 'container'; div.textContent = 'This is a dynamically created div'; // 添加到 body 中 document.body.appendChild(div); //创建嵌套元素 // 创建父节点 const parentDiv = document.createElement('div'); parentDiv.className = 'parent'; // 创建子节点 const childSpan = document.createElement('span'); childSpan.textContent = 'I am a child element'; // 将子节点插入父节点 parentDiv.appendChild(childSpan); // 将父节点插入到页面 document.body.appendChild(parentDiv); //动态插入到特定位置 const newDiv = document.createElement('div'); newDiv.textContent = 'Inserted before existing content'; const referenceNode = document.getElementById('existingElement'); referenceNode.parentNode.insertBefore(newDiv, referenceNode);
node.appendChild
: 将新创建的元素添加为父节点的子节点。// 当需要动态创建并插入大量节点时,直接操作 DOM 可能导致性能问题。DocumentFragment 是一个轻量级的文档片段,可以减少对 DOM 的多次操作 const fragment = document.createDocumentFragment(); for (let i = 0; i < 100; i++) { const div = document.createElement('div'); div.textContent = `Item ${i + 1}`; fragment.appendChild(div); } // 一次性插入到 DOM document.body.appendChild(fragment);
parentNode.insertBefore
: 在指定节点前插入新节点。node.removeChild
: 删除子节点。const element = document.getElementById('myDiv'); if (element) { element.parentNode.removeChild(element); // 删除该节点 }
element.innerHTML
: 设置或获取 HTML 内容。//⚠️ 注意:innerHTML 会替换节点内的所有内容,不适用于复杂 DOM 操作 const container = document.createElement('div'); container.innerHTML = ` <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> `; document.body.appendChild(container);
①在index.html引入路径
<script type="text/javascript" src="/static/js/EasyPlayer-pro.js"></script>
②封装视频组件
<template>
<div class="easy-player-container">
<!-- 为每个播放器容器添加唯一的类 -->
<div id="player_box1" class="player-box"></div>
</div>
</template>
<script>
/* global EasyPlayerPro */
export default {
name: 'EasyPlayerPro',
props: {
initialConfig: {
type: Object,
default: () => ({}),
},
},
data () {
return {
player: '',
playerInstances: {}, // 存储播放器实例
config: {
hasAudio: true,
isLive: true,
MSE: false,
WCS: false,
...this.initialConfig,
},
};
},
beforeUnmount () {
this.destroyAllPlayers();
},
methods: {
// 设置视频 URL,如果播放器不存在则创建新播放器
setVideoUrl (url, id, changeId) {
this.player = changeId;
const videoObject = { url, id };
const player = this.playerInstances[id];
if (player) {
player.play(url).catch(e => {
console.error(`播放失败 (播放器${id}):`, e);
this.$emit('play-error', e);
});
} else {
this.createPlayer(id, url);
}
},
// 创建单个播放器实例
createPlayer (id, url) {
if (this.playerInstances[id]) {
console.log(`播放器 ${id} 已存在,不重复创建`);
return;
}
this.$nextTick(() => {
setTimeout(() => {
const container = document.getElementById(`${this.player}`)
if (!container || !(container instanceof Element)) {
console.error(`未找到有效容器,ID: ${id}`);
return;
}
const player = new EasyPlayerPro(container, {
demuxType: "webrtc",
isLive: this.config.isLive,// 是否直播
bufferTime: 0.2,// 缓冲时间
stretch: false, // 是否拉伸
MSE: this.config.MSE,// 是否使用MSE
WCS: this.config.WCS,// 是否使用WCS
hasAudio: true,// 是否有音频
// hasVideo: true,// 是否有视频
// hasSubtitle: true,// 是否有字幕
watermark: {
// 水印
text: { content: 'easyplayer-pro' },
right: 10,
top: 10,
},
});
player.play(url)
.then(() => {
this.$emit('play-started', id);
})
.catch((e) => {
console.error(`播放失败 (播放器${id}):`, e);
this.$emit('play-error', e);
});
// 添加事件监听
player.on("fullscreen", (flag) => {
this.$emit('fullscreen-change', flag);
});
player.on('playbackRate', (rate) => {
player.setRate(rate);
this.$emit('rate-change', rate);
});
player.on('playbackSeek', (data) => {
this.$emit('seek', data);
});
this.playerInstances[id] = player;
}, 100); // 延迟100毫秒
});
},
// 销毁所有播放器实例
destroyAllPlayers () {
Object.keys(this.playerInstances).forEach(id => {
this.destroyPlayer(id);
});
},
// 销毁单个播放器实例
destroyPlayer (id) {
const player = this.playerInstances[id];
if (player) {
player.destroy();
delete this.playerInstances[id];
}
}
},
};
</script>
<style scoped>
.easy-player-container {
width: 100%;
background: #000;
height: 100%;
position: relative;
}
.player-box {
background: #000;
}
</style>
J
③应用
<template>
<div class="video-box">
<EasyWebRTC ref="videoRef"></EasyWebRTC>
</div>
</template>
<script>
import EasyWebRTC from "@/components/EasyWebRTC.vue";//引入自己存储的封装组件路径
let url = "指定播放的url路径"
onMounted(() => {
nextTick(() => {
if (videoRef.value) {
const containerId = `videoId`
videoRef.value.setVideoUrl(
url, containerId, containerId
)
const parentEle = document.getElementsByClassName('video-box')
if (parentEle) {
const targetChild = parentEle.querySelector('#player_box1');
if (targetChild) {
targetChild.id = `${containerId}`; // 修改 id
} else {
console.warn('未找到 id 为 "player_box1" 的孙子节点');
}
} else {
console.warn('未找到父元素:', `${containerId}`);
}
} else {
console.error("EasyPlayerRef 未挂载");
}
})
})
</script>