Add sample for vite + vue

This commit is contained in:
Dennis Chen 2025-09-17 14:30:28 +08:00
parent 1b33d5dced
commit 668420adc0
11 changed files with 1268 additions and 0 deletions

View file

@ -0,0 +1,70 @@
# Monaco Editor with Vue.js and Vite
这是一个使用Vue.js 3、Vite和Monaco Editor的示例项目。
## 特性
- ✅ Vue.js 3 Composition API
- ✅ TypeScript 支持
- ✅ Vite 构建工具
- ✅ Monaco Editor 集成
- ✅ 语法高亮和代码补全
- ✅ 多语言支持TypeScript、JavaScript、JSON、CSS、HTML
## 安装
```bash
npm install
```
## 运行
开发模式:
```bash
npm run dev
```
构建生产版本:
```bash
npm run build
```
预览构建版本:
```bash
npm run serve
```
## 项目结构
```
src/
├── components/
│ └── Editor.vue # Monaco Editor 组件
├── main.ts # Vue 应用入口
├── userWorker.ts # Monaco Editor Workers 配置
└── vite-env.d.ts # TypeScript 类型声明
```
## 技术栈
- Vue.js 3
- TypeScript
- Vite
- Monaco Editor
## 对比 React 版本
这个 Vue 版本与 React 版本功能相同,主要区别:
1. 使用 Vue 3 Composition API 替代 React Hooks
2. 使用 `@vitejs/plugin-vue` 替代 `@vitejs/plugin-react`
3. 使用 `.vue` 单文件组件替代 `.tsx` 文件
4. 使用 `createApp` 替代 `ReactDOM.render`
## Monaco Editor 配置
Monaco Editor 通过 Web Workers 运行,支持以下语言:
- TypeScript/JavaScript
- JSON
- CSS/SCSS/Less
- HTML/Handlebars/Razor

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>browser-esm-vite-vue</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
{
"name": "browser-esm-vite-vue",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"serve": "vite preview",
"simpleserver": "node ../node_modules/yaserver/bin/yaserver --root ./dist --port 9999"
},
"dependencies": {},
"devDependencies": {
"monaco-editor": "^0.32.0",
"vue": "^3.3.4",
"@vitejs/plugin-vue": "^2.3.4",
"typescript": "^5.4.5",
"vue-tsc": "^1.8.5",
"vite": "^2.9.17"
}
}

View file

@ -0,0 +1,31 @@
<template>
<div class="editor" ref="editorContainer"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
const editorContainer = ref<HTMLDivElement | null>(null);
let editor: monaco.editor.IStandaloneCodeEditor | null = null;
onMounted(() => {
if (editorContainer.value) {
editor = monaco.editor.create(editorContainer.value, {
value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
language: 'typescript'
});
}
});
onUnmounted(() => {
editor?.dispose();
});
</script>
<style scoped>
.editor {
width: 100vw;
height: 100vh;
}
</style>

View file

@ -0,0 +1,5 @@
import { createApp } from 'vue';
import Editor from './components/Editor.vue';
import './userWorker';
createApp(Editor).mount('#app');

View file

@ -0,0 +1,27 @@
import * as monaco from 'monaco-editor';
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
// @ts-ignore
self.MonacoEnvironment = {
getWorker(_: any, label: string) {
if (label === 'json') {
return new jsonWorker();
}
if (label === 'css' || label === 'scss' || label === 'less') {
return new cssWorker();
}
if (label === 'html' || label === 'handlebars' || label === 'razor') {
return new htmlWorker();
}
if (label === 'typescript' || label === 'javascript') {
return new tsWorker();
}
return new editorWorker();
}
};
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);

View file

@ -0,0 +1,7 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

View file

@ -0,0 +1,25 @@
{
"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,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View file

@ -0,0 +1,10 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View file

@ -0,0 +1,7 @@
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()]
});