Alpine.js变量变化调用方法问题:模态框重开未初始化相机
解决Alpine.js模态框重新打开时相机不初始化的问题
问题根源
x-init 是Alpine.js的初始化指令,仅会在DOM元素首次渲染完成时执行一次。你的模态框关闭后并未被销毁,只是通过CSS隐藏,因此再次打开时不会触发x-init,自然不会重新初始化相机。
解决方案
借助Bootstrap模态框的原生事件(shown.bs.modal/hidden.bs.modal),在模态框显示/隐藏时主动触发相机的初始化和清理逻辑,替代x-init的一次性执行逻辑。
修改后的完整代码
HTML结构
<div x-data="initTestData()" @data-transfer.window="check=$event.detail.check; runningTest=true;" class="modal fade" @shown.bs.modal="initTest(check)" @hidden.bs.modal="closeTest()"> <video class="w-100 rounded" id="test-video"> </video> </div>
触发代码(无需修改)
<i @click="$dispatch('data-transfer', {check: check})" data-bs-toggle="modal" role="button"></i>
JavaScript定义(优化后)
function initTestData() { console.log('init test data'); return { check: null, resource: null, runningTest: false, initTest(check) { console.log('Check initialized: ', check); // 先清理已有流,避免重复申请相机资源 if (this.resource) { this.resource.getTracks().forEach(track => track.stop()); this.resource = null; } const video = document.getElementById('test-video'); navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user' } }).then(stream => { this.resource = stream; if ("srcObject" in video) { video.srcObject = stream; } else { video.src = window.URL.createObjectURL(stream); } video.onloadedmetadata = function () { video.play(); }; }).catch(err => { console.error('相机初始化失败:', err); }); }, closeTest() { this.runningTest = false; if (this.resource) { this.resource.getTracks().forEach(track => track.stop()); this.resource = null; } // 重置video元素,避免残留上一次的画面 const video = document.getElementById('test-video'); video.srcObject = null; if (video.src) { window.URL.revokeObjectURL(video.src); video.src = ''; } } } }
关键修改说明
- 移除video标签的
x-init:放弃仅执行一次的初始化逻辑,改用模态框事件触发。 - 添加
@shown.bs.modal监听:Bootstrap模态框完全显示时触发该事件,此时调用initTest()重新初始化相机。 - 添加
@hidden.bs.modal监听:模态框关闭隐藏时触发该事件,调用closeTest()停止相机流并清理资源,避免内存泄漏。 - 优化
initTest逻辑:初始化前先检查并停止已有流,防止重复申请相机权限导致冲突。
内容的提问来源于stack exchange,提问作者Anuj TBE
相关产品推荐
相关产品推荐

