之前在《CodeMirror实现自定义提示功能》中介绍过CodeMirror实现自定义提示功能的一种实现方式,但是之前的实现有一些局限性,主要是:1、需要提示的内容是从variablePool中读取的,需要先确定variablePool;2、提示的内容需要一个个去选择,不支持搜索功能。
本文提供了一种解决上述两个问题的实现方式,不同的主要是handleShowHint这个方法,修改了一些提示逻辑。具体代码如下:
handleShowHint() {
const {modelData, modelPointsAttributes} = this.props.configureStore;
const modelDataList = modelData.map(item => (item.modelId));
const codeMirrorInstance = this.codeEditorRef.getCodeMirrorInstance();
const cur = this.codeEditor.getCursor();
const curLine = this.codeEditor.getLine(cur.line);
const end = cur.ch;
const start = end;
let list = [];
// 根据不同情况给list赋值,默认为[],即不显示提示框。
const cursorTwoCharactersBefore = `${curLine.charAt(start - 2)}${curLine.charAt(start - 1)}`;
if (cursorTwoCharactersBefore === '${') {
list = modelDataList;
} else if (cursorTwoCharactersBefore === '::') {
const lastIndex = curLine.lastIndexOf('${', start);
const modelId = curLine.substring(lastIndex + 2, start - 2);
if (modelPointsAttributes[modelId]) {
list = modelPointsAttributes[modelId];
} else {
list = [];
this.props.configureStore.getModelPointsAttributes(modelId, this.handleHint);
}
} else {
const lastStartIndex = curLine.lastIndexOf('${', start);
const lastEndIndex = curLine.lastIndexOf('}', start);
const lastColonIndex = curLine.lastIndexOf('::', start);
if (start > lastStartIndex && (start <= lastColonIndex || lastColonIndex < lastStartIndex)) {
const modelId = curLine.substring(lastStartIndex + 2, start);
list = modelDataList.filter(item => (item.indexOf(modelId) !== -1));
// eslint-disable-next-line
return {list, from: codeMirrorInstance.Pos(cur.line, lastStartIndex + 2), to: codeMirrorInstance.Pos(cur.line, end)};
} else if (start > lastStartIndex && start > lastColonIndex && (start <= lastEndIndex || (lastEndIndex < lastColonIndex && lastEndIndex < lastStartIndex))) {
const modelId = curLine.substring(lastStartIndex + 2, lastColonIndex);
const pointAttrId = curLine.substring(lastColonIndex + 2, start);
if (modelPointsAttributes[modelId]) {
list = modelPointsAttributes[modelId].filter(item => (item.indexOf(pointAttrId) !== -1));
// eslint-disable-next-line
return {list, from: codeMirrorInstance.Pos(cur.line, lastColonIndex + 2), to: codeMirrorInstance.Pos(cur.line, end)};
}
}
}
// eslint-disable-next-line
return {list, from: codeMirrorInstance.Pos(cur.line, start), to: codeMirrorInstance.Pos(cur.line, end)};
}
实现中使用如下代码请求所选模型下点:
this.props.configureStore.getModelPointsAttributes(modelId, this.handleHint);
具体实现在mobx的store中,不再贴相应代码。
需要注意的是:
- 我在项目里使用了mobx管理state,发请求的位置在store中,不在组件内,所以通过回调函数的形式当接口数据成功返回后调用this.handleHint来进行提示;
- 需要注意提供正确的提示框的位置,类似于下边的形式:
{list, from: codeMirrorInstance.Pos(cur.line, lastColonIndex + 2), to: codeMirrorInstance.Pos(cur.line, end)};
- codemirror提供了一种基于Promise的异步提示方式,因为我发请求的操作不在组件里,所以没有使用,在可以的情况下,Promise的实现应该会更合适。