非框架适配DevqalySDK在Vue中报错`v is not defined`的解决及SDK构建咨询
说明
我知道此处可能并非此类问题的合适提问场所,但我寻求相关指导,并非需要确切的最终答案,因我明白该问题具有开放性。
背景介绍
我开发了一个用于监听浏览器点击、窗口缩放及其他各类事件的包DevqalySDK。
正常使用场景
在无框架的简单项目中(仅将TS转译为JS)本地导入该包时,可正常使用,一切功能正常运行:
<script type="module"> import { DevqalySDK } from '/src/index.ts' const devqaly = new DevqalySDK({ projectKey: '99851ecf-af1e-4e0b-9118-466babf48a3a', }) devqaly.showRecordingButton() </script>
Vue项目中的异常情况
当我在通过npx init vue@latest创建的Vue初始项目中尝试使用该包时:
<script setup lang="ts"> import { RouterLink, RouterView } from 'vue-router' import HelloWorld from './components/HelloWorld.vue' import {DevqalySDK} from '@devqaly/browser' import { onMounted } from "vue"; onMounted(() => { const sdk = new DevqalySDK({ projectKey: 'project-key' }) sdk.showRecordingButton() console.log('asd') }) </script>
出现如下错误:ReferenceError: v is not defined
经调试,定位到触发错误的代码部分:
// sdk.ts import { writeRecordingScript } from './services/RecordingService' export class DevqalySDK { private async onRecordingStart() { const newWindow = window.open() if (!newWindow) throw new DevqalyError('Cant create window') newWindow.document.write(writeRecordingScript()) } } // RecordingService.ts export function writeRecordingScript() { const code = '(' + function () { class RecordingService { stream recorder dataPromise async start() { const stream = await navigator.mediaDevices.getDisplayMedia() this.stream = stream const recorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=vp9', }) recorder.start() this.recorder = recorder const channel = new BroadcastChannel('devqaly') channel.onmessage = async _e => { this.stop() } this.recorder.ondataavailable = ev => { channel.postMessage(ev.data) window.close() } channel.postMessage('started') window.onbeforeunload = _e => { channel.postMessage('cancel') } } stop() { this.recorder.stop() this.stream.getTracks().forEach(t => t.stop()) return this.dataPromise } } async function main() { const recorder = new RecordingService() const message = document.createElement('h1') try { await recorder.start() message.innerText = 'Recording started, go back to your app and leave this tab open! Do not close this tab, closing it will cancel the session.' } catch (e) { message.innerText = 'User clicked cancel on the recording screen picker' } document.body.append(message) } main().catch(console.error) } + ')' return ` <script> ${code}() </script> <body> </body> ` }
查看浏览器中转译后的生成代码,可见:
(function() { class e { constructor() { v(this, "stream"); v(this, "recorder"); v(this, "dataPromise"); } async start() { const i = await navigator.mediaDevices.getDisplayMedia(); this.stream = i; const o = new MediaRecorder(i, { mimeType: "video/webm;codecs=vp9" }); o.start(), this.recorder = o; const l = new BroadcastChannel("devqaly"); l.onmessage = async (f) => { this.stop(); }, this.recorder.ondataavailable = (f) => { l.postMessage(f.data), window.close(); }, l.postMessage("started"), window.onbeforeunload = (f) => { l.postMessage("cancel"); }; } stop() { return this.recorder.stop(), this.stream.getTracks().forEach((i) => i.stop()), this.dataPromise; } } async function t() { const n = new e(), i = document.createElement("h1"); try { await n.start(), i.innerText = "Recording started, go back to your app and leave this tab open! Do not close this tab, closing it will cancel the session."; } catch { i.innerText = "User clicked cancel on the recording screen picker"; } document.body.append(i); } t().catch(console.error); })()
其中构造函数中的v未定义,这正是报错原因。
问题咨询
- 该错误是否与
window.open()获取的是Shadow DOM而非普通DOM有关?我对此存疑,但已无其他调试思路 - 如何构建既能适配无框架简单项目、又能兼容各类前端框架的DOM事件监听SDK?求相关学习资源
补充信息
SDK项目的tsconfig.json配置如下:
{ "compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], "skipLibCheck": true, /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "types": ["cypress", "@testing-library/cypress"] }, "include": ["src", "src/services"] }
内容的提问来源于stack exchange,提问作者Bruno Francisco
相关产品推荐
相关产品推荐

