<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
近期要完成一個程式碼編輯器的內容,用的vue3.0+ts+vite架構,學習尚淺, 常在外掛上遇坑
特此記錄下在monaco-editor的使用
需求:yaml和sql的檔案的高亮、補全
1.安裝
// ^0.34.1 yarn add monaco-editor
2.在vite.config.js中設定(如果不需要tsjshtml就不需要這麼做)
// 強制預構建外掛包 optimizeDeps: { include: [ `monaco-editor/esm/vs/language/json/json.worker`, `monaco-editor/esm/vs/language/css/css.worker`, `monaco-editor/esm/vs/language/html/html.worker`, `monaco-editor/esm/vs/language/typescript/ts.worker`, `monaco-editor/esm/vs/editor/editor.worker` ], },
3.元件封裝與使用
monacoEditor.vue元件
<template> <div ref="codeEditBox" class="codeEditBox" :class="hightChange&&'codeEditBox1'" /> </template> <script lang="ts"> import { defineComponent, onBeforeUnmount, onMounted, ref, watch, } from 'vue' 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' import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' import * as monaco from 'monaco-editor' import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/sql/sql.js'; import { language as yamlLanguage } from 'monaco-editor/esm/vs/basic-languages/yaml/yaml.js'; import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution' import { editorProps } from './monacoEditorType' export default defineComponent({ name: 'MonacoEditor', props: editorProps, emits: ['update:modelValue', 'change', 'editor-mounted'], setup(props, { emit }) { (self as any).MonacoEnvironment = { getWorker(_: string, label: string) { if (label === 'json') { return new JsonWorker() } if (['css', 'scss', 'less'].includes(label)) { return new CssWorker() } if (['html', 'handlebars', 'razor'].includes(label)) { return new HtmlWorker() } if (['typescript', 'javascript'].includes(label)) { return new TsWorker() } return new EditorWorker() }, } let editor: any const codeEditBox = ref() const init = () => { monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({ noSemanticValidation: true, noSyntaxValidation: false, }) monaco.languages.typescript.javascriptDefaults.setCompilerOptions({ target: monaco.languages.typescript.ScriptTarget.ES2020, allowNonTsExtensions: true, }) monaco.languages.registerCompletionItemProvider('sql', { provideCompletionItems() { const suggestions:any = []; // 這個keywords就是sql.js檔案中有的 sqlLanguage.keywords.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Keyword, insertText: item, }); }) sqlLanguage.operators.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Operator, insertText: item, }); }) sqlLanguage.builtinFunctions.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Function, insertText: item, }); }) sqlLanguage.builtinVariables.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Variable, insertText: item, }); }) return { // 最後要返回一個陣列 suggestions, }; }, }) monaco.languages.registerCompletionItemProvider('yaml', { provideCompletionItems() { const suggestions:any = []; // 這個keywords就是python.js檔案中有的 yamlLanguage.keywords.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Keyword, insertText: item, }); }) return { // 最後要返回一個陣列 suggestions, }; }, }) editor = monaco.editor.create(codeEditBox.value, { value: props.modelValue, language: props.language, readOnly: props.readOnly, theme: props.theme, ...props.options, }) // 監聽值的變化 editor.onDidChangeModelContent(() => { const value = editor.getValue() // 給父元件實時返回最新文字 emit('update:modelValue', value) emit('change', value) }) emit('editor-mounted', editor) } watch( () => props.modelValue, (newValue) => { if (editor) { const value = editor.getValue() if (newValue !== value) { editor.setValue(newValue) } } }, ) watch( () => props.options, (newValue) => { editor.updateOptions(newValue) }, { deep: true }, ) watch( () => props.readOnly, () => { console.log('props.readOnly', props.readOnly) editor.updateOptions({ readOnly: props.readOnly }) }, { deep: true }, ) watch( () => props.language, (newValue) => { monaco.editor.setModelLanguage(editor.getModel()!, newValue) }, ) onBeforeUnmount(() => { editor.dispose() }) onMounted(() => { init() }) return { codeEditBox } }, }) </script> <style lang="scss" scoped> .codeEditBox { width: 100%; flex: 1; min-height: 100px; // height: 200px; overflow-y: auto; } .codeEditBox1{ height: calc(100% - 323px); } </style>
4.monacoEditorType.ts型別定義檔案
import { PropType } from 'vue' export type Theme = 'vs' | 'hc-black' | 'vs-dark' export type FoldingStrategy = 'auto' | 'indentation' export type RenderLineHighlight = 'all' | 'line' | 'none' | 'gutter' export interface Options { automaticLayout: boolean // 自適應佈局 foldingStrategy: FoldingStrategy // 摺疊方式 auto | indentation renderLineHighlight: RenderLineHighlight // 行亮 selectOnLineNumbers: boolean // 顯示行號 placeholder:string minimap: { // 關閉小地圖 enabled: boolean } // readOnly: Boolean // 唯讀 fontSize: number // 字型大小 scrollBeyondLastLine: boolean // 取消程式碼後面一大段空白 overviewRulerBorder: boolean // 不要卷軸的邊框 } export const editorProps = { modelValue: { type: String as PropType<string>, default: null, }, hightChange: { type: Boolean, default: false, }, width: { type: [String, Number] as PropType<string | number>, default: '100%', }, height: { type: [String, Number] as PropType<string | number>, default: '100%', }, language: { type: String as PropType<string>, default: 'javascript', }, readOnly: { type: Boolean, default: false, }, theme: { type: String as PropType<Theme>, validator(value: string): boolean { return ['vs', 'hc-black', 'vs-dark', 'hc-light'].includes(value) }, default: 'vs', }, options: { type: Object as PropType<Options>, default() { return { automaticLayout: true, // foldingStrategy: 'indentation', foldingStrategy: 'indentation', // 摺疊方式 auto | indentation // renderLineHighlight: 'all', renderLineHighlight: 'all' || 'line' || 'none' || 'gutter', // 行亮 selectOnLineNumbers: true, // 顯示行號 minimap: { // 關閉小地圖 enabled: false, }, placeholder: 'ss', // readOnly: false, // 唯讀 fontSize: 16, // 字型大小 scrollBeyondLastLine: false, // 取消程式碼後面一大段空白 overviewRulerBorder: false, // 不要卷軸的邊框 } }, }, }
5.在父元件中使用
<monacoEditor v-model="value" :language="language" :hight-change="hightChange" :read-only="tablist.length===0" width="100%" height="100%" @editor-mounted="editorMounted" /> import monacoEditor from './monacoEditor.vue' const value = ref('-- select * from infrastructure;') const language = ref('sql') const hightChange = ref<any>(false) const editorMounted = (editor: any) => { console.log('editor範例載入完成', editor) }
value:編輯器程式碼顯示的值
language:要載入的語言型別
hightChange:改變編輯器的高度(可去掉,我這邊有個sql查表的實現,需要在編輯區下面加一個sql查詢的表格,所以需要這個引數)
read-only:編輯區是否是唯讀的,當左側檔案樹為空時沒有檔案,編輯區不可寫
editorMounted:載入完成操作
//記得在env.d.ts設定包的 declare module 'monaco-editor'; declare module 'monaco-editor/esm/vs/language/typescript/ts.worker?worker' declare module 'monaco-editor/esm/vs/basic-languages/sql/sql.js'; declare module 'monaco-editor/esm/vs/basic-languages/yaml/yaml.js'; declare module 'monaco-editor/esm/vs/language/json/json.worker?worker' declare module 'monaco-editor/esm/vs/language/css/css.worker?worker' declare module 'monaco-editor/esm/vs/language/html/html.worker?worker' declare module 'monaco-editor/esm/vs/editor/editor.worker?worker' declare module 'monaco-editor/esm/vs/basic-languages/javascript/javascript.js'
yarn build 時會發生下述報錯
我在這裡看到了解決辦法https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md
在monacoEditor.vue元件,重寫getWorker方法
<template> <div ref="codeEditBox" class="codeEditBox" :class="hightChange&&'codeEditBox1'" /> </template> <script lang="ts"> import { defineComponent, onBeforeUnmount, onMounted, ref, watch, } from 'vue' // 減去以下包 -- 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' -- import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' import * as monaco from 'monaco-editor' import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/sql/sql.js'; import { language as yamlLanguage } from 'monaco-editor/esm/vs/basic-languages/yaml/yaml.js'; import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution' import 'monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution' import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution' import { editorProps } from './monacoEditorType' export default defineComponent({ name: 'MonacoEditor', props: editorProps, emits: ['update:modelValue', 'change', 'editor-mounted'], setup(props, { emit }) { (self as any).MonacoEnvironment = { ++ getWorker: (_: string, label: string) => { ++ const getWorkerModule = (moduleUrl:string, label:string) => new Worker((self as any).MonacoEnvironment.getWorkerUrl(moduleUrl), { ++ name: label, ++ type: 'module', ++ }); ++ switch (label) { ++ case 'json': ++ return getWorkerModule('/monaco-editor/esm/vs/language/json/json.worker?worker', label); ++ case 'css': ++ case 'scss': ++ case 'less': ++ return getWorkerModule('/monaco-editor/esm/vs/language/css/css.worker?worker', label); ++ case 'html': ++ case 'handlebars': ++ case 'razor': ++ return getWorkerModule('/monaco-editor/esm/vs/language/html/html.worker?worker', label); ++ case 'typescript': ++ case 'javascript': ++ return getWorkerModule('/monaco-editor/esm/vs/language/typescript/ts.worker?worker', label); ++ default: ++ return getWorkerModule('/monaco-editor/esm/vs/editor/editor.worker?worker', label); ++ } ++ }, // 原來的減去 -- getWorker(_: string, label: string) { -- if (label === 'json') { -- return new JsonWorker() -- } -- if (['css', 'scss', 'less'].includes(label)) { -- return new CssWorker() -- } -- if (['html', 'handlebars', 'razor'].includes(label)) { -- return new HtmlWorker() -- } -- if (['typescript', 'javascript'].includes(label)) { -- return new TsWorker() -- } -- return new EditorWorker() -- }, } let editor: any const codeEditBox = ref() const init = () => { monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({ noSemanticValidation: true, noSyntaxValidation: false, }) monaco.languages.typescript.javascriptDefaults.setCompilerOptions({ target: monaco.languages.typescript.ScriptTarget.ES2020, allowNonTsExtensions: true, }) monaco.languages.registerCompletionItemProvider('sql', { provideCompletionItems() { const suggestions:any = []; // 這個keywords就是sql.js檔案中有的 sqlLanguage.keywords.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Keyword, insertText: item, }); }) sqlLanguage.operators.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Operator, insertText: item, }); }) sqlLanguage.builtinFunctions.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Function, insertText: item, }); }) sqlLanguage.builtinVariables.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Variable, insertText: item, }); }) return { // 最後要返回一個陣列 suggestions, }; }, }) monaco.languages.registerCompletionItemProvider('yaml', { provideCompletionItems() { const suggestions:any = []; // 這個keywords就是python.js檔案中有的 yamlLanguage.keywords.forEach((item:any) => { suggestions.push({ label: item, kind: monaco.languages.CompletionItemKind.Keyword, insertText: item, }); }) return { // 最後要返回一個陣列 suggestions, }; }, }) editor = monaco.editor.create(codeEditBox.value, { value: props.modelValue, language: props.language, readOnly: props.readOnly, theme: props.theme, ...props.options, }) // 監聽值的變化 editor.onDidChangeModelContent(() => { const value = editor.getValue() // 給父元件實時返回最新文字 emit('update:modelValue', value) emit('change', value) }) emit('editor-mounted', editor) } watch( () => props.modelValue, (newValue) => { if (editor) { const value = editor.getValue() if (newValue !== value) { editor.setValue(newValue) } } }, ) watch( () => props.options, (newValue) => { editor.updateOptions(newValue) }, { deep: true }, ) watch( () => props.readOnly, () => { console.log('props.readOnly', props.readOnly) editor.updateOptions({ readOnly: props.readOnly }) }, { deep: true }, ) watch( () => props.language, (newValue) => { monaco.editor.setModelLanguage(editor.getModel()!, newValue) }, ) onBeforeUnmount(() => { editor.dispose() }) onMounted(() => { init() }) return { codeEditBox } }, }) </script> <style lang="scss" scoped> .codeEditBox { width: 100%; flex: 1; min-height: 100px; // height: 200px; overflow-y: auto; } .codeEditBox1{ height: calc(100% - 323px); } </style>
到此這篇關於vue3+vite+ts使用monaco-editor編輯器的文章就介紹到這了,更多相關vue3+vite+ts使用monaco-editor內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45