您好,登錄后才能下訂單哦!
這篇文章主要介紹了怎么使用Monaco Editor開(kāi)發(fā)SQL代碼提示編輯器的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇怎么使用Monaco Editor開(kāi)發(fā)SQL代碼提示編輯器文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。
安裝依賴(lài),這里請(qǐng)注意版本
yarn add monaco-editor@0.29.1 yarn add monaco-editor-webpack-plugin@5.0.0
配置 webpack 插件
// vue.config.js ... const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin') module.export = { ... configureWebpack: { name: name, resolve: { alias: { '@': resolve('src'), }, }, plugins: [new MonacoWebpackPlugin()], }, ... }
請(qǐng)注意 monaco-editor-webpack-plugin 和 monaco-editor 的對(duì)應(yīng)關(guān)系,否則可能會(huì)出現(xiàn)無(wú)法運(yùn)行的情況。
monaco-editor-webpack-plugin | monaco-editor |
---|---|
7.*.* | >= 0.31.0 |
6.*.* | 0.30.* |
5.*.* | 0.29.* |
4.*.* | 0.25.*, 0.26.*, 0.27.*, 0.28.* |
3.*.* | 0.22.*, 0.23.*, 0.24.* |
2.*.* | 0.21.* |
1.9.* | 0.20.* |
1.8.* | 0.19.* |
1.7.* | 0.18.* |
先上干貨!
<template> <div ref="codeContainer" class="editor-container" : /> </template> <script> import * as monaco from 'monaco-editor' /** * VS Code 編輯器 * * 通過(guò) getEditorVal 函數(shù)向外傳遞編輯器即時(shí)內(nèi)容 * 通過(guò) initValue 用于初始化編輯器內(nèi)容。 * 編輯器默認(rèn) sql 語(yǔ)言,支持的語(yǔ)言請(qǐng)參考 node_modules\monaco-editor\esm\vs\basic-languages 目錄下~ * 編輯器樣式僅有 'vs', 'vs-dark', 'hc-black' 三種 */ export default { name: 'MonacoEditor', props: { initValue: { type: String, default: '', }, readOnly: Boolean, language: { type: String, default: 'sql', }, height: { type: Number, default: 300, }, theme: { type: String, default: 'vs', }, }, data() { return { monacoEditor: null, // 語(yǔ)言編輯器 } }, computed: { inputVal() { return this.monacoEditor?.getValue() }, }, watch: { inputVal() { if (this.monacoEditor) { this.$emit('change', this.monacoEditor.getValue()) } }, theme() { this.setTheme(this.theme) }, height() { this.layout() }, }, mounted() { this.initEditor() }, beforeDestroy() { if (this.monacoEditor) { this.monacoEditor.dispose() } }, methods: { initEditor() { if (this.$refs.codeContainer) { this.registerCompletion() // 初始化編輯器,確保dom已經(jīng)渲染 this.monacoEditor = monaco.editor.create(this.$refs.codeContainer, { value: '', // 編輯器初始顯示文字 language: 'sql', // 語(yǔ)言 readOnly: this.readOnly, // 是否只讀 Defaults to false | true automaticLayout: true, // 自動(dòng)布局 theme: this.theme, // 官方自帶三種主題vs, hc-black, or vs-dark minimap: { // 關(guān)閉小地圖 enabled: false, }, tabSize: 2, // tab縮進(jìn)長(zhǎng)度 }) } this.setInitValue() }, focus() { this.monacoEditor.focus() }, layout() { this.monacoEditor.layout() }, getValue() { return this.monacoEditor.getValue() }, // 將 initValue Property 同步到編輯器中 setInitValue() { this.monacoEditor.setValue(this.initValue) }, setTheme() { monaco.editor.setTheme(this.theme) }, getSelectionVal() { const selection = this.monacoEditor.getSelection() // 獲取光標(biāo)選中的值 const { startLineNumber, endLineNumber, startColumn, endColumn } = selection const model = this.monacoEditor.getModel() return model.getValueInRange({ startLineNumber, startColumn, endLineNumber, endColumn, }) }, setPosition(column, lineNumber) { this.monacoEditor.setPosition({ column, lineNumber }) }, getPosition() { return this.monacoEditor.getPosition() }, }, } </script> <style lang="scss" scoped></style>
getSelectionVal() { const selection = this.monacoEditor.getSelection() // 獲取光標(biāo)選中的值 const { startLineNumber, endLineNumber, startColumn, endColumn } = selection const model = this.monacoEditor.getModel() return model.getValueInRange({ startLineNumber, startColumn, endLineNumber, endColumn, }) },
insertStringInTemplate(str) { const selection = this.monacoEditor.getSelection() // 獲取光標(biāo)選中的值 const { startLineNumber, endLineNumber, startColumn, endColumn } = selection const model = this.monacoEditor.getModel() const textBeforeSelection = model.getValueInRange({ startLineNumber: 1, startColumn: 0, endLineNumber: startLineNumber, endColumn: startColumn, }) const textAfterSelection = model.getValueInRange({ startLineNumber: endLineNumber, startColumn: endColumn, endLineNumber: model.getLineCount(), endColumn: model.getLineMaxColumn(model.getLineCount()), }) this.monacoEditor.setValue(textBeforeSelection + str + textAfterSelection) this.monacoEditor.focus() this.monacoEditor.setPosition({ lineNumber: startLineNumber, column: startColumn + str.length, }) },
setPosition(column, lineNumber) { this.monacoEditor.setPosition({ column, lineNumber }) }, getPosition() { return this.monacoEditor.getPosition() },
首先由后端提供具體的庫(kù)表信息:
export const hintData = { adbs: ['dim_realtime_recharge_paycfg_range', 'dim_realtime_recharge_range'], dimi: ['ads_adid', 'ads_spec_adid_category'], }
然后根據(jù)已有庫(kù)表信息進(jìn)行自定義 AutoComplete
import * as monaco from 'monaco-editor' import { language } from 'monaco-editor/esm/vs/basic-languages/sql/sql' const { keywords } = language export default { ... mounted() { this.initEditor() }, methods: { ... registerCompletion() { const _that = this monaco.languages.registerCompletionItemProvider('sql', { triggerCharacters: ['.', ...keywords], provideCompletionItems: (model, position) => { let suggestions = [] const { lineNumber, column } = position const textBeforePointer = model.getValueInRange({ startLineNumber: lineNumber, startColumn: 0, endLineNumber: lineNumber, endColumn: column, }) const tokens = textBeforePointer.trim().split(/\s+/) const lastToken = tokens[tokens.length - 1] // 獲取最后一段非空字符串 if (lastToken.endsWith('.')) { const tokenNoDot = lastToken.slice(0, lastToken.length - 1) if (Object.keys(_that.hintData).includes(tokenNoDot)) { suggestions = [..._that.getTableSuggest(tokenNoDot)] } } else if (lastToken === '.') { suggestions = [] } else { suggestions = [..._that.getDBSuggest(), ..._that.getSQLSuggest()] } return { suggestions, } }, }) }, // 獲取 SQL 語(yǔ)法提示 getSQLSuggest() { return keywords.map((key) => ({ label: key, kind: monaco.languages.CompletionItemKind.Enum, insertText: key, })) }, getDBSuggest() { return Object.keys(this.hintData).map((key) => ({ label: key, kind: monaco.languages.CompletionItemKind.Constant, insertText: key, })) }, getTableSuggest(dbName) { const tableNames = this.hintData[dbName] if (!tableNames) { return [] } return tableNames.map((name) => ({ label: name, kind: monaco.languages.CompletionItemKind.Constant, insertText: name, })) }, initEditor() { if (this.$refs.codeContainer) { this.registerCompletion() // 初始化編輯器,確保dom已經(jīng)渲染 this.monacoEditor = monaco.editor.create(this.$refs.codeContainer, { value: '', // 編輯器初始顯示文字 language: 'sql', // 語(yǔ)言 readOnly: this.readOnly, // 是否只讀 Defaults to false | true automaticLayout: true, // 自動(dòng)布局 theme: this.theme, // 官方自帶三種主題vs, hc-black, or vs-dark minimap: { // 關(guān)閉小地圖 enabled: false, }, tabSize: 2, // tab縮進(jìn)長(zhǎng)度 }) } this.setValue(this.value) }, } }
resize() { this.monacoEditor.layout() },
注意!設(shè)置主題并非在編輯器實(shí)例上修改的哦!
setTheme() { monaco.editor.setTheme(this.theme) },
編輯器自身不支持 sql 格式化(試了下 JavaScript 是支持的),所以用到了 sql-formatter 這個(gè)庫(kù)。
import { format } from 'sql-formatter' ... format() { this.monacoEditor.setValue( format(this.monacoEditor.getValue(), { indentStyle: 'tabularLeft', }), ) }, ...
需要安裝以下兩個(gè)庫(kù)
npm install monaco-editor-nls --save npm install monaco-editor-esm-webpack-plugin --save-dev
beforeDestroy() { if (this.monacoEditor) { this.monacoEditor.dispose() } },
下面是我遇到的幾個(gè)坑。
最新版本的 Monaco Editor 已經(jīng)使用了 ES2022 的語(yǔ)法,所以老項(xiàng)目可能會(huì)出現(xiàn)編譯不過(guò)的問(wèn)題。所以我把版本調(diào)低了一些。
在最初調(diào)試編輯器的時(shí)候出現(xiàn)了無(wú)法編輯的情況,后來(lái)發(fā)現(xiàn)是同事用到了 default-passive-events 這個(gè)庫(kù)來(lái)關(guān)閉 chrome 的 Added non-passive event listener to a scroll-blocking <some> event. Consider marking event handler as 'passive' to make the page more responsive 警告。結(jié)果攔截一些 event。
一開(kāi)始我看它的官方文檔是非常懵的,各種接口、函數(shù)、對(duì)象的定義,完全不像是個(gè)前端庫(kù)那么好理解。鼓搗了好久才慢慢找到門(mén)路。
先看示例
查看它的 playground,上面其實(shí)是有一些功能可以直接找到的。
查看它在 github 上的 /samples 目錄,里面也有不少示例。
去掘金這類(lèi)網(wǎng)站上找別人寫(xiě)的示例,能有不少啟發(fā)。
再看 API
了解了自己所需要的功能相關(guān)的代碼,再去看它文檔的 API 就會(huì)發(fā)現(xiàn)容易理解多了。逐步發(fā)散理解更多關(guān)聯(lián)功能。
關(guān)于“怎么使用Monaco Editor開(kāi)發(fā)SQL代碼提示編輯器”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“怎么使用Monaco Editor開(kāi)發(fā)SQL代碼提示編輯器”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。