简介
Vue Playground支持选择不同的Vue版本,实时编码并实时预览。本文主要介绍其如何实现选择不同的Vue版本。
核心代码
store.ts — vuejs/repl — GitHub1s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| async setVueVersion(version: string) { this.vueVersion = version const compilerUrl = `https://unpkg.com/@vue/compiler-sfc@${version}/dist/compiler-sfc.esm-browser.js` const runtimeUrl = `https://unpkg.com/@vue/runtime-dom@${version}/dist/runtime-dom.esm-browser.js` const ssrUrl = `https://unpkg.com/@vue/server-renderer@${version}/dist/server-renderer.esm-browser.js` this.pendingCompiler = import( compilerUrl) this.compiler = await this.pendingCompiler this.pendingCompiler = null this.state.vueRuntimeURL = runtimeUrl this.state.vueServerRendererURL = ssrUrl const importMap = this.getImportMap() const imports = importMap.imports || (importMap.imports = {}) imports.vue = runtimeUrl imports['vue/server-renderer'] = ssrUrl this.setImportMap(importMap) this.forceSandboxReset() console.info(`[@vue/repl] Now using Vue version: ${version}`) }
|
https://github1s.com/vuejs/repl/blob/HEAD/src/output/Preview.vue#L52
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| watch(() => store.state.resetFlip, createSandbox)
function createSandbox() { if (sandbox) { proxy.destroy() stopUpdateWatcher && stopUpdateWatcher() container.value.removeChild(sandbox) }
sandbox = document.createElement('iframe') sandbox.setAttribute( 'sandbox', [ 'allow-forms', 'allow-modals', 'allow-pointer-lock', 'allow-popups', 'allow-same-origin', 'allow-scripts', 'allow-top-navigation-by-user-activation' ].join(' ') )
const importMap = store.getImportMap() if (!importMap.imports) { importMap.imports = {} } if (!importMap.imports.vue) { importMap.imports.vue = store.state.vueRuntimeURL } const sandboxSrc = srcdoc.replace( /<!--IMPORT_MAP-->/, JSON.stringify(importMap) ) sandbox.srcdoc = sandboxSrc container.value.appendChild(sandbox)
proxy = new PreviewProxy(sandbox, { on_fetch_progress: (progress: any) => { }, on_error: (event: any) => { const msg = event.value instanceof Error ? event.value.message : event.value if ( msg.includes('Failed to resolve module specifier') || msg.includes('Error resolving module specifier') ) { runtimeError.value = msg.replace(/\. Relative references must.*$/, '') + `.\nTip: edit the "Import Map" tab to specify import paths for dependencies.` } else { runtimeError.value = event.value } }, on_unhandled_rejection: (event: any) => { let error = event.value if (typeof error === 'string') { error = { message: error } } runtimeError.value = 'Uncaught (in promise): ' + error.message }, on_console: (log: any) => { if (log.duplicate) { return } if (log.level === 'error') { if (log.args[0] instanceof Error) { runtimeError.value = log.args[0].message } else { runtimeError.value = log.args[0] } } else if (log.level === 'warn') { if (log.args[0].toString().includes('[Vue warn]')) { runtimeWarning.value = log.args .join('') .replace(/\[Vue warn\]:/, '') .trim() } } }, on_console_group: (action: any) => { }, on_console_group_end: () => { }, on_console_group_collapsed: (action: any) => { } })
sandbox.addEventListener('load', () => { proxy.handle_links() stopUpdateWatcher = watchEffect(updatePreview) }) }
|
结论
更换Vue
版本时,从unpkg
获取了构建完毕的Vue runtime
, 并重建了用于渲染结果的iframe
。
参考 & 引用
https://sfc.vuejs.org/
core/packages/sfc-playground/src at main · vuejs/core (github.com)
vuejs/repl: Vue SFC REPL as a Vue 3 component (github.com)