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', // 語(yǔ)言
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, // 自動(dòng)布局
// overviewRulerBorder: false, // 不要滾動(dòng)條的邊框
codeLens: true, // 代碼鏡頭
scrollBeyondLastLine: true, // 滾動(dòng)完最后一行后再滾動(dòng)一屏幕
colorDecorators: true, // 顏色裝飾器
accessibilitySupport: 'on', // 輔助功能支持 "auto" | "off" | "on"
lineNumbers: 'on', // 行號(hào) 取值: "on" | "off" | "relative" | "interval" | function
lineNumbersMinChars: 5, // 行號(hào)最小字符 number
// enableSplitViewResizing: 'on',
// readOnly: false, // 是否只讀 取值 true | false
fixedOverflowWidgets: true,
quickSuggestions: true,
// acceptSuggestionOnEnter: 'on',
theme: 'vs',
formatOnPaste: true, // 粘貼時(shí)自動(dòng)格式化
}
onMounted(() => {
initAutoCompletion()
init()
})
onUnmounted(() => {
editor.dispose()
})
function init() {
// 使用 - 創(chuàng)建 monacoEditor 對(duì)象
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: 初始化自動(dòng)補(bǔ)全
*/
function initAutoCompletion() {
monaco.languages.registerCompletionItemProvider('sql', {
// 觸發(fā)提示的字符
triggerCharacters: ['.', ' ', ...keywords],
provideCompletionItems: (model, position) => {
let suggestions: any = []
// 行號(hào),列號(hào)
const { lineNumber, column } = position
// 光標(biāo)之前的所有字符,即從這一行的 0 到當(dāng)前的字符
const textBeforePointer = model.getValueInRange({
startLineNumber: lineNumber,
startColumn: 0,
endLineNumber: lineNumber,
endColumn: column,
})
// trim() 取消兩邊空格,保證拆分出來(lái)前后都不是空值
// \s是指空白,包括空格、換行、tab縮進(jìn)等所有的空白
const words = textBeforePointer.trim().split(/\s+/)
// 最后的一個(gè)有效詞
const lastWord = words[words.length - 1]
if (lastWord.endsWith('.')) {
// 如果這個(gè)詞以 . 結(jié)尾,那么認(rèn)為是希望補(bǔ)全表的字段
// 拿到真實(shí)的表名,把 . 去掉
const tableName = lastWord.slice(0, lastWord.length - 1)
if (Object.keys(tables).includes(tableName)) {
suggestions = [...getFieldsSuggest(tableName)]
}
} else if (lastWord === '.') {
// 如果這個(gè)詞本身就是一個(gè) . 即點(diǎn)前面是空的,那么什么都不用補(bǔ)全了
// 按理說(shuō)這應(yīng)該是個(gè)語(yǔ)法錯(cuò)誤
suggestions = []
} else {
// 其他時(shí)候都補(bǔ)全表名,以及關(guān)鍵字
suggestions = [...getTableSuggest(), ...getKeywordsSuggest()]
}
return {
suggestions,
}
},
})
}
/**
* @description: 獲取關(guān)鍵字的補(bǔ)全列表
* @tips: CompletionItemKind 的所有枚舉可以在monaco.d.ts 文件中找到,有二十多個(gè),取需即可
*/
function getKeywordsSuggest() {
return keywords.map((key) => ({
label: key, // 顯示的名稱
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: key, // 真實(shí)補(bǔ)全的值
}))
}
/**
* @description: 獲取表名的補(bǔ)全列表
*/
function getTableSuggest() {
return Object.keys(tables).map((key) => ({
label: key, // 顯示的名稱
kind: monaco.languages.CompletionItemKind.Variable,
insertText: key, // 真實(shí)補(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ā)生變化時(shí)觸發(fā),如:輸入、刪除、粘貼等
雙向綁定
由于在外部動(dòng)態(tài)改變initValue的值無(wú)法更新編輯器的值,所以添加watch監(jiān)聽initValue的值動(dòng)態(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用vue/cli出現(xiàn)defineConfig?is?not?function錯(cuò)誤解決辦法
這篇文章主要給大家介紹了關(guān)于使用vue/cli出現(xiàn)defineConfig?is?not?function錯(cuò)誤的解決辦法,當(dāng)我們?cè)谧龃虬渲玫臅r(shí)候,出現(xiàn)了這個(gè)錯(cuò)誤,需要的朋友可以參考下2023-11-11
vue form表單post請(qǐng)求結(jié)合Servlet實(shí)現(xiàn)文件上傳功能
這篇文章主要介紹了vue form表單post請(qǐng)求結(jié)合Servlet實(shí)現(xiàn)文件上傳功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
Vue.js設(shè)計(jì)與實(shí)現(xiàn)分支切換與清除學(xué)習(xí)總結(jié)
這篇文章主要為大家介紹了Vue.js設(shè)計(jì)與實(shí)現(xiàn)分支切換與清除學(xué)習(xí)總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Vue格式化數(shù)據(jù)后切換頁(yè)面出現(xiàn)NaN問(wèn)題及解決
這篇文章主要介紹了Vue格式化數(shù)據(jù)后切換頁(yè)面出現(xiàn)NaN問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
vue中style設(shè)置scoped后部分樣式不生效的解決
這篇文章主要介紹了vue中style設(shè)置scoped后部分樣式不生效的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09
Vue ElementUI之Form表單驗(yàn)證遇到的問(wèn)題
這篇文章主要介紹了Vue ElementUI之Form表單驗(yàn)證遇到的問(wèn)題,需要的朋友可以參考下2017-08-08

