React使用CodeMirror实现SQL输入提示编辑器
今天老大让我把原来的SQL编辑器放到新的平台上,然后我对照原来的编辑器,然后再修改了一下,形成了一个全新的SQL输入提示编辑器,先上图看看效果,然后再详细讲解怎么实现
一、编辑器效果
1.1 关键词提示效果图
1.2 数据库和表格选择提示效果
二、具体实现
我们的项目主要用到了React+CodeMirror组件,在实例化的的editor对象中,每输入一个词,再弹出相对应的自动选择提示框,有两种方式,第一种方式用到了CodeMirror2插件,第二种方式,直接用原生的CodeMirror编辑器,然后再修改一下,我们这里用到的第二种方式多了一个功能,就是在编辑器中输入分号( ; )时,不要提示,但是第一种方法没办法配置,如果各位大佬实现了的,可以给我留言,告诉我怎么解决,接下来解析一下两种方案的实现
2.1 依赖下载
yarn add codemirror
yarn add react-codemirror2 //第二种方案没有用到这个依赖
2.2 方案一
import React from 'react';
import { UnControlled as CodeMirror } from 'react-codemirror2'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/sql/sql';
import 'codemirror/mode/shell/shell';
import 'codemirror/addon/display/placeholder';
import 'codemirror/addon/hint/show-hint.css'; // 用来做代码提示
import 'codemirror/addon/hint/show-hint.js'; // 用来做代码提示
import 'codemirror/addon/hint/sql-hint.js'; // 用来做代码提示
export default class SqlConsole extends React.Component {
state = {};
static defaultProps = {
options: {
mode: 'text/x-mysql',
lineNumbers: true,
styleActiveLine: true,
cursorHeight: 1,
autofocus: true,
extraKeys: {
}
}
}
render() {
const { options } = this.props;
return (<div style={{ width: '100%', height: '100%', fontSize: '16px' }}>
<CodeMirror
value="select * from word"
options={options}
onInputRead={(editor, change) => {
//库和表名显示,一般是库名中包含一个表名数组,但是要在第一级显示,也需要把表名加进去
var data = { test: ['t_user', 'menu', 'auth_info'], t_user: [], menu: [''], default: ['tableinfo'] };
editor.setOption('hintOptions', {
tables: data,
completeSingle: false
});
editor.execCommand('autocomplete');
}}
/>
</div>
);
}
}
2.3 方案二
import React from 'react';
import codemirror from 'codemirror';
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/sql/sql';
import 'codemirror/mode/shell/shell';
import 'codemirror/addon/display/placeholder';
import 'codemirror/addon/hint/show-hint.css'; // 用来做代码提示
import 'codemirror/addon/hint/show-hint.js'; // 用来做代码提示
import 'codemirror/addon/hint/sql-hint.js'; // 用来做代码提示
import 'codemirror/theme/3024-day.css'
export default class SqlConsole1 extends React.Component {
editor = null;
componentDidMount() {
this.editor = codemirror(this.ref, {
indentWithTabs: true,
smartIndent: true,
lineNumbers: true,
matchBrackets: true,
autofocus: true,
extraKeys: {
"';'": this.completeAfter //添加;号监听
},
hintOptions: { completeSingle: false },
lineWrapping: true,//在长行时文字是换行(wrap)还是滚动(scroll),默认为滚动(scroll)。
mode: 'text/x-mysql',
value: 'select * from word'
});
this.editor.on('inputRead', (editor, change) => {
var data = { test: ['t_user', 'menu', 'auth_info'], t_user: [], menu: [''], default: ['tableinfo'] };
editor.setOption('hintOptions', {
tables: data,
completeSingle: false
});
editor.execCommand('autocomplete');
});
}
completeAfter = (editor) => {
var spaces = Array(editor.getOption("indentUnit")).join(";");//分号;监听执行完后,就不会再执行inputRead输入监听了
editor.replaceSelection(spaces);
}
render() {
return (<div ref={(self) => { this.ref = self; }} style={{ width: '100%', height: '100%', fontSize: '16px' }}></div>);
}
}
以上就是两种方案的实现效果,方案二比方案一多了一个功能,就是用户在一行后面输入份好,不需要提示的时候,可以灵活控制取消功能