您现在的位置是:网站首页> 编程资料编程资料
Monaco Editor开发SQL代码提示编辑器实例详解_vue.js_
2023-05-24
304人已围观
简介 Monaco Editor开发SQL代码提示编辑器实例详解_vue.js_
安装
安装依赖,这里请注意版本
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()], }, ... } 请注意 monaco-editor-webpack-plugin 和 monaco-editor 的对应关系,否则可能会出现无法运行的情况。
| 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.* |
简易 SQL 编辑器
先上干货!
相关功能
获取选中代码
getSelectionVal() { const selection = this.monacoEditor.getSelection() // 获取光标选中的值 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() // 获取光标选中的值 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() }, 自定义 SQL 库表提示,并保留原有 SQL 提示
首先由后端提供具体的库表信息:
export const hintData = { adbs: ['dim_realtime_recharge_paycfg_range', 'dim_realtime_recharge_range'], dimi: ['ads_adid', 'ads_spec_adid_category'], } 然后根据已有库表信息进行自定义 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 语法提示 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已经渲染 this.monacoEditor = monaco.editor.create(this.$refs.codeContainer, { value: '', // 编辑器初始显示文字 language: 'sql', // 语言 readOnly: this.readOnly, // 是否只读 Defaults to false | true automaticLayout: true, // 自动布局 theme: this.theme, // 官方自带三种主题vs, hc-black, or vs-dark minimap: { // 关闭小地图 enabled: false, }, tabSize: 2, // tab缩进长度 }) } this.setValue(this.value) }, } } 编辑器 resize
resize() { this.monacoEditor.layout() }, 编辑器设置主题
注意!设置主题并非在编辑器实例上修改的哦!
setTheme() { monaco.editor.setTheme(this.theme) }, SQL 代码格式化
编辑器自身不支持 sql 格式化(试了下 JavaScript 是支持的),所以用到了 sql-formatter 这个库。
import { format } from 'sql-formatter' ... format() { this.monacoEditor.setValue( format(this.monacoEditor.getValue(), { indentStyle: 'tabularLeft', }), ) }, ... 右键菜单汉化
需要安装以下两个库
npm install monaco-editor-nls --save npm install monaco-editor-esm-webpack-plugin --save-dev
具体用法可以直接去 www.npmjs.com/package/mon… 里面看,我就不搬运了~
记得销毁编辑器对象哦
beforeDestroy() { if (this.monacoEditor) { this.monacoEditor.dispose() } }, 踩坑
下面是我遇到的几个坑。
- 最新版本的 Monaco Editor 已经使用了 ES2022 的语法,所以老项目可能会出现编译不过的问题。所以我把版本调低了一些。
- 在最初调试编辑器的时候出现了无法编辑的情况,后来发现是同事用到了 default-passive-events 这个库来关闭 chrome 的 Added non-passive event listener to a scroll-blocking
event. Consider marking event handler as 'passive' to make the page more responsive 警
相关内容
- vue使用monaco editor汉化右键菜单示例_vue.js_
- JavaScript箭头函数的五种使用方法及三点注意事项_javascript技巧_
- react项目升级报错,babel报错,.babelrc配置兼容等问题及解决_React_
- JavaScript扩展运算符的学习及应用详情(ES6)_javascript技巧_
- Node.js Process对象详解_node.js_
- JavaScript遍历对象的七种方法汇总_javascript技巧_
- JS实现点击文本框改变背景颜色_javascript技巧_
- 使用useImperativeHandle时父组件第一次没拿到子组件的问题_React_
- React Native 中实现倒计时功能_React_
- vue3深入学习 nextTick和historyApiFallback_vue.js_
