Web Component视频无法显示:点击按钮后仅能听到音频
问题分析与修复方案
核心错误原因
你的代码里存在一个关键错误:在startStreaming的Promise回调中,const shadowRoot = this;这行代码错误地将组件实例赋值给了shadowRoot变量,而实际上应该引用组件的shadow根节点(this.shadowRoot)。这导致你创建的video元素并没有被添加到正确的shadow DOM容器中,因此浏览器无法渲染视频画面,而音频不受影响是因为媒体流本身已经成功获取。
快速修复版本
只需修改回调中的shadowRoot引用,即可让视频正常显示:
class WebStream extends LitElement { constructor(){ super(); this.attachShadow({ mode: 'open' }); } render() { return html` <button @click="${this.startStreaming}">start streaming</button> `; } startStreaming() { navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(function(mediaStream){ // 修复:正确获取组件的shadow根节点 const shadowRoot = this.shadowRoot; let shadow = document.createElement("div") shadowRoot.appendChild(shadow); this.video = document.createElement('video'); shadow.appendChild(this.video); this.video.srcObject = mediaStream console.log(mediaStream) this.video.setAttribute("width", "320"); this.video.setAttribute("height", "240"); this.video.play() }.bind(this)) .catch(function(error){ console.log(error) }) } } customElements.define('web-stream', WebStream);
符合LitElement最佳实践的版本
LitElement的设计理念是通过响应式状态驱动视图,不建议手动操作DOM。下面是更规范的写法,通过响应式属性控制视频的渲染:
import { LitElement, html } from 'lit'; class WebStream extends LitElement { static properties = { // 定义响应式属性,用于存储媒体流 mediaStream: { type: Object } }; constructor(){ super(); this.mediaStream = null; } render() { return html` <button @click="${this.startStreaming}">start streaming</button> <!-- 根据mediaStream是否存在渲染视频元素 --> ${this.mediaStream ? html` <video .srcObject="${this.mediaStream}" width="320" height="240" autoplay ></video> ` : ''} `; } async startStreaming() { try { const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); // 更新响应式属性,触发视图重新渲染 this.mediaStream = mediaStream; } catch (error) { console.log(error); } } } customElements.define('web-stream', WebStream);
说明
- 最佳实践版本中,我们通过
static properties定义了响应式属性mediaStream,当该属性更新时,LitElement会自动重新渲染模板,无需手动创建和添加DOM元素。 - 使用
autoplay属性替代手动调用play()方法,更符合HTML标准,同时避免潜在的播放权限问题。
内容的提问来源于stack exchange,提问作者hmn99
相关产品推荐
相关产品推荐

