CodeMirror实现自定义提示功能增强版(支持搜索、调用接口查询提示内容)

之前在《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的实现应该会更合适。

你可能感兴趣的:(codemirror)