vue3.0-monaco組件封裝存檔代碼解析
vue3.0-monaco組件封裝存檔
<template> <div ref="main" class="codeEditBox editor-container" style="width: 100%; height: 400px" /> </template> <script lang="ts" setup> import { ref, onMounted, onUnmounted } from 'vue' import * as monaco from 'monaco-editor' import { language } from 'monaco-editor/esm/vs/basic-languages/sql/sql' const { keywords } = language const main = ref() const tables = { users: ['name', 'id', 'email', 'phone', 'password'], roles: ['id', 'name', 'order', 'created_at', 'updated_at', 'deleted_at'], } let editor: monaco.editor.IStandaloneCodeEditor const props = defineProps({ initValue: { type: String, default: '', }, }) const emit = defineEmits(['update:initValue', 'change', 'ctrlS']) const defaultOptions: any = { // theme, // 主題 value: props.initValue, // 默認(rèn)顯示的值 language: 'sql', // 語言 folding: true, // 是否折疊 minimap: { // 關(guān)閉小地圖 enabled: false, }, wordWrap: 'on', wrappingIndent: 'indent', foldingHighlight: true, // 折疊等高線 foldingStrategy: 'indentation', // 折疊方式 auto | indentation showFoldingControls: 'always', // 是否一直顯示折疊 always | mouseover disableLayerHinting: true, // 等寬優(yōu)化 emptySelectionClipboard: false, // 空選擇剪切板 selectionClipboard: true, // 選擇剪切板 // automaticLayout: true, // 自動布局 // overviewRulerBorder: false, // 不要滾動條的邊框 codeLens: true, // 代碼鏡頭 scrollBeyondLastLine: true, // 滾動完最后一行后再滾動一屏幕 colorDecorators: true, // 顏色裝飾器 accessibilitySupport: 'on', // 輔助功能支持 "auto" | "off" | "on" lineNumbers: 'on', // 行號 取值: "on" | "off" | "relative" | "interval" | function lineNumbersMinChars: 5, // 行號最小字符 number // enableSplitViewResizing: 'on', // readOnly: false, // 是否只讀 取值 true | false fixedOverflowWidgets: true, quickSuggestions: true, // acceptSuggestionOnEnter: 'on', theme: 'vs', formatOnPaste: true, // 粘貼時自動格式化 } onMounted(() => { initAutoCompletion() init() }) onUnmounted(() => { editor.dispose() }) function init() { // 使用 - 創(chuàng)建 monacoEditor 對象 editor = monaco.editor.create( document.querySelector('.codeEditBox') as HTMLElement, defaultOptions, ) // 監(jiān)聽值的變化 editor.onDidChangeModelContent((val: any) => { const text = editor.getValue() emit('update:initValue', text) }) } // 覆蓋默認(rèn)ctrl+s瀏覽器保存 onMounted(() => { window.addEventListener('keydown', handleKeyDown) }) const handleKeyDown = (event) => { if (event.ctrlKey && event.key === 's') { event.preventDefault() // 阻止瀏覽器默認(rèn)的保存操作 // 執(zhí)行調(diào)試 emit('ctrlS') } } /** * @description: 初始化自動補(bǔ)全 */ function initAutoCompletion() { monaco.languages.registerCompletionItemProvider('sql', { // 觸發(fā)提示的字符 triggerCharacters: ['.', ' ', ...keywords], provideCompletionItems: (model, position) => { let suggestions: any = [] // 行號,列號 const { lineNumber, column } = position // 光標(biāo)之前的所有字符,即從這一行的 0 到當(dāng)前的字符 const textBeforePointer = model.getValueInRange({ startLineNumber: lineNumber, startColumn: 0, endLineNumber: lineNumber, endColumn: column, }) // trim() 取消兩邊空格,保證拆分出來前后都不是空值 // \s是指空白,包括空格、換行、tab縮進(jìn)等所有的空白 const words = textBeforePointer.trim().split(/\s+/) // 最后的一個有效詞 const lastWord = words[words.length - 1] if (lastWord.endsWith('.')) { // 如果這個詞以 . 結(jié)尾,那么認(rèn)為是希望補(bǔ)全表的字段 // 拿到真實的表名,把 . 去掉 const tableName = lastWord.slice(0, lastWord.length - 1) if (Object.keys(tables).includes(tableName)) { suggestions = [...getFieldsSuggest(tableName)] } } else if (lastWord === '.') { // 如果這個詞本身就是一個 . 即點前面是空的,那么什么都不用補(bǔ)全了 // 按理說這應(yīng)該是個語法錯誤 suggestions = [] } else { // 其他時候都補(bǔ)全表名,以及關(guān)鍵字 suggestions = [...getTableSuggest(), ...getKeywordsSuggest()] } return { suggestions, } }, }) } /** * @description: 獲取關(guān)鍵字的補(bǔ)全列表 * @tips: CompletionItemKind 的所有枚舉可以在monaco.d.ts 文件中找到,有二十多個,取需即可 */ function getKeywordsSuggest() { return keywords.map((key) => ({ label: key, // 顯示的名稱 kind: monaco.languages.CompletionItemKind.Keyword, insertText: key, // 真實補(bǔ)全的值 })) } /** * @description: 獲取表名的補(bǔ)全列表 */ function getTableSuggest() { return Object.keys(tables).map((key) => ({ label: key, // 顯示的名稱 kind: monaco.languages.CompletionItemKind.Variable, insertText: key, // 真實補(bǔ)全的值 })) } watch(() => props.initValue, (newVal) => { console.log('newVal', newVal) editor.setValue(newVal) }) /** * @description: 根據(jù)表名獲取字段補(bǔ)全列表 * @param {*} tableName */ function getFieldsSuggest(tableName) { const fields = tables[tableName] if (!fields) { return [] } return fields.map((name) => ({ label: name, kind: monaco.languages.CompletionItemKind.Field, insertText: name, })) } </script> <style> .editor-container { border: 1px solid #ccc; } </style>
解析
editor.onDidChangeModelContent
當(dāng)編輯器內(nèi)容發(fā)生變化時觸發(fā),如:輸入、刪除、粘貼等
雙向綁定
由于在外部動態(tài)改變initValue的值無法更新編輯器的值,所以添加watch監(jiān)聽initValue的值動態(tài)設(shè)置進(jìn)編輯器
watch(() => props.initValue, (newVal) => { editor.setValue(newVal) })
使用
<MonacoEditor language="JSON" v-model:initValue="clickItem.form" ref="monacoRef" />
到此這篇關(guān)于vue3.0-monaco組件封裝存檔的文章就介紹到這了,更多相關(guān)vue3.0組件封裝存檔內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用vue/cli出現(xiàn)defineConfig?is?not?function錯誤解決辦法
這篇文章主要給大家介紹了關(guān)于使用vue/cli出現(xiàn)defineConfig?is?not?function錯誤的解決辦法,當(dāng)我們在做打包配置的時候,出現(xiàn)了這個錯誤,需要的朋友可以參考下2023-11-11vue form表單post請求結(jié)合Servlet實現(xiàn)文件上傳功能
這篇文章主要介紹了vue form表單post請求結(jié)合Servlet實現(xiàn)文件上傳功能,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01Vue.js設(shè)計與實現(xiàn)分支切換與清除學(xué)習(xí)總結(jié)
這篇文章主要為大家介紹了Vue.js設(shè)計與實現(xiàn)分支切換與清除學(xué)習(xí)總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Vue格式化數(shù)據(jù)后切換頁面出現(xiàn)NaN問題及解決
這篇文章主要介紹了Vue格式化數(shù)據(jù)后切換頁面出現(xiàn)NaN問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06vue中style設(shè)置scoped后部分樣式不生效的解決
這篇文章主要介紹了vue中style設(shè)置scoped后部分樣式不生效的解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-09-09