<template>
<div>
<div class="textareaBox" ref="textarea"></div>
</div>
</template>
<script>
import * as monaco from 'monaco-editor'
// import customKeywords from './customKeywords'
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'
window.MonacoEnvironment = {
// 提供一个定义worker路径的全局变量
getWorker (_, label) {
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都会去加载他。
}
}
export default {
name: 'codeMirror',
props: {
hiddentip: {
type: Boolean,
default: false
},
// 语言 目前只有 html css js
language: {
type: String,
default: 'javascript'
}
},
data () {
return {
monacoEditor: null,
code: ''
}
},
destroyed () {
this.destroyCodeMorror()
},
methods: {
initCodeMirror () {
if (this.language == 'javascript') {
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true)
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true,
noSyntaxValidation: false
})
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES2020,
allowNonTsExtensions: true
})
} else if (this.language == 'json') {
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
validate: true,
enableSchemaRequest: true
})
}
this.monacoEditor = monaco.editor.create(this.$refs.textarea, {
theme: 'vs-dark', // 主题
value: this.code, // 默认显示的值
language: this.language,
folding: true, // 是否折叠
foldingHighlight: true, // 折叠等高线
foldingStrategy: 'auto', // 折叠方式
showFoldingControls: 'always', // 是否一直显示折叠
disableLayerHinting: true, // 等宽优化
emptySelectionClipboard: false, // 空选择剪切板
selectionClipboard: false, // 选择剪切板
automaticLayout: true, // 自动布局
codeLens: true, // 代码镜头
scrollBeyondLastLine: false, // 滚动完最后一行后再滚动一屏幕
colorDecorators: true, // 颜色装饰器
accessibilitySupport: 'on', // 辅助功能支持"auto" | "off" | "on"
lineNumbers: 'on', // 行号 取值: "on" | "off" | "relative" | "interval" | function
lineNumbersMinChars: 4, // 行号最小字符 number
enableSplitViewResizing: false,
readOnly: false, //是否只读 取值 true | false
fontSize: 16
})
this.monacoEditor.onDidChangeModelContent(() => {
this.$emit('change', this.monacoEditor.getValue())
})
let self = this
Object.defineProperty(this, 'code', {
configurable: true, // 表示能否通过delete删除属性,能否再次修改属性描述符,默认false
enumerable: true, // 表示该属性是否可枚举(for...in循环、Object.keys()等),默认false
get: function () {
return self.monacoEditor.getValue()
},
set: function (val) {
return val
}
})
},
initCustomLanguage () {
monaco.languages.registerCompletionItemProvider('javascript', {
provideCompletionItems: function (model, position) {
// 获取当前行数
const line = position.lineNumber
// 获取当前列数
const column = position.column
// 获取当前输入行的所有内容
const content = model.getLineContent(line)
// 通过下标来获取当前光标后一个内容,即为刚输入的内容
const sym = content[column - 2]
var word = model.getWordUntilPosition(position)
var range = {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: word.startColumn,
endColumn: word.endColumn
}
//---------------------------------------------------
//上面的代码仅仅是为了获取sym,即提示符
//---------------------------------------------------
var suggestions = []
//直接提示,以下为javascript语句关键词提示
var javascriptList = [
'var',
'let',
'const',
'Promise',
'$tu',
'new',
'for',
'forEach',
'etx.meta2d'
]
for (var i in javascriptList) {
suggestions.push({
label: javascriptList[i], // 显示的提示内容
kind: monaco.languages.CompletionItemKind['Keyword'], // 用来显示提示内容后的不同的图标
insertText: javascriptList[i], // 选择后粘贴到编辑器中的文字
detail: '', // 提示内容后的说明
range: range
})
}
return {
suggestions: suggestions
}
},
triggerCharacters: ['']
})
},
destroyCodeMorror () {
this.monacoEditor.dispose()
},
_initialize () {
this.initCodeMirror()
this.initCustomLanguage() // 自定义提示词语
}
}
}
</script>
<style scoped>
.textareaBox {
height: 500px;
font-size: 16px;
font-weight: 800;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica,
Segoe UI, Arial, Roboto, PingFang SC, miui, Hiragino Sans GB,
Microsoft Yahei, sans-serif, Avenir;
}
.textareaBox .cm-activeLine {
background-color: transparent;
}
</style>
{
"name": "mate2d",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"@vitejs/plugin-vue2": "^2.3.1",
"vite": "^5.4.10"
},
"dependencies": {
"axios": "^1.7.7",
"codemirror": "^6.0.1",
"echarts": "^5.5.1",
"element-ui": "^2.15.14",
"jquery": "^3.7.1",
"monaco-editor": "0.30.1",
"vue": "2.7.14",
"vuex": "3.6.2"
}
}
// vite.config.js
import vue from '@vitejs/plugin-vue2'
import { resolve } from 'path'
export default {
plugins: [vue()],
server: {
host: '192.168.8.30', // can be overwritten by process.env.HOST
port: 1081
},
base: './',
resolve: {
alias: {
'@': resolve(__dirname, './src')
}
},
build: {
minify: false
}
}