CodeMirror实现自定义提示功能

没有检索到摘要

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我之前在文章《CodeMirror基本使用及实现关键词高亮、自定义主题》中简单介绍了CodeMirror实现自动提示的功能,但是使用的是CodeMirror中封装好的几种指定语法的提示功能,如css、html、js、sql、xml,对应文件如下列表:

现在我开发中有需求做自定义语法的自动提示功能,并没有现成的mode可以使用,学习CodeMirror API和上述几个文件的实现方式之后找到了实现方法,记录一下我的实现方式。

本文以${model::point}为例,需求是输入${后直接出现下拉框,提示内容是所有的model,当选择或输入model后,输入::直接出现下拉框,提示内容为${后::前model里所有的point和attribute,在${和::后点击Ctrl,也出现和上面相同的提示信息。

要提示的数据举例如下:

 

{
    "model_a":{
        "points":[
            "point_a1",
            "point_a2",
            "point_a3"
        ],
        "attributes":[
            "attribute_a1",
            "attribute_a2",
            "attribute_a3"
        ]
    },
    "model_b":{
        "points":[
            "point_b1",
            "point_b2",
            "point_b3"
        ],
        "attributes":[
            "attribute_b1",
            "attribute_b2",
            "attribute_b3"
        ]
    }
}

 要实现的效果如下:

实现方式:

import React, {Component} from 'react';
import autobind from 'class-autobind';
import {inject, observer} from 'mobx-react';
import CodeMirror from 'react-codemirror';
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/show-hint.js';
import 'codemirror/addon/hint/anyword-hint.js';
import 'codemirror/lib/codemirror.css';
import './index.less';

@inject('configureStore')
@observer
export default class CodeEditor extends Component {
    constructor(props) {
        super(props);
        autobind(this, CodeEditor.prototype);
        this.options = {
            lineNumbers: false,
            // mode: {name: "text/x-mysql"},
            extraKeys: {"Ctrl": "autocomplete"},
            theme: 'sqlTheme',
            lineWrapping:true,
            hintOptions: {hint: this.handleShowHint, completeSingle: false}
        };
    }
    componentDidMount(){
        this.codeEditor = this.codeEditorRef.getCodeMirror();
    }

    handleShowHint(){
        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)}`;
        const {activeItem, openedItemsData} = this.props.configureStore;
        const {variablePool} = openedItemsData[activeItem].config;
        const variablePoolKeys = variablePool ? Object.keys(variablePool): [];
        if(cursorTwoCharactersBefore === '${'){
            list = variablePoolKeys;
        }else if(cursorTwoCharactersBefore === '::'){
            const lastIndex = curLine.lastIndexOf('${', start);
            const modelId = curLine.substring(lastIndex + 2, start - 2);
            if(lastIndex !== -1 && modelId && variablePool[modelId]){
                list = variablePool[modelId].attributes.concat(variablePool[modelId].points);
            }else {
                list = [];
            }
        }
        return {list: list, from: codeMirrorInstance.Pos(cur.line, start), to: codeMirrorInstance.Pos(cur.line, end)};
    }
    handleCodeChange(value){
        this.codeEditor.closeHint();
        this.codeEditor.showHint();
        this.props.onChange(value);
    }

    render() {
        return (
            <CodeMirror
                ref={ref => this.codeEditorRef = ref}
                value={this.props.value}
                onChange={this.handleCodeChange}
                options={this.options}
            />
        );
    }
}

demo中使用了mobx管理state,variablePool是从configureStore中读取的。

更新:这里介绍的方式需要提前准备好提示的内容,且不支持搜索,只能选择。在《CodeMirror实现自定义提示功能增强版(支持搜索、调用接口查询提示内容)》里更新了一个增强版,可以支持所有和调用接口查询提示数据。

 

### Vue2 中使用 CodeMirror 实现自定义 JavaScript 代码提示 要在 Vue2 中通过 CodeMirror 实现带有 JavaScript 的代码提示并进行自定义,可以按照以下方式完成: #### 安装依赖 首先需要安装 `codemirror` 和其相关扩展包: ```bash npm install codemirror @codemirror/view @codemirror/state @codemirror/autocomplete --save ``` #### 创建组件 创建一个名为 `CodeEditor.vue` 的组件来封装 CodeMirror 编辑器的功能。 以下是完整的实现代码: ```vue <template> <div class="code-editor"> <textarea ref="editor"></textarea> </div> </template> <script> import CodeMirror from "codemirror"; import "codemirror/lib/codemirror.css"; // 样式文件 import "codemirror/mode/javascript/javascript.js"; // 支持 JavaScript 语法高亮 import "codemirror/addon/hint/show-hint.js"; // 提示功能插件 import "codemirror/addon/hint/show-hint.css"; // 提示样式 export default { name: "CodeEditor", props: { value: { type: String, default: "", }, }, data() { return { editorInstance: null, // 存储 CodeMirror 实例 }; }, watch: { value(newValue) { const currentValue = this.editorInstance.getValue(); if (newValue !== currentValue) { this.editorInstance.setValue(newValue); } }, }, mounted() { this.initEditor(); // 初始化编辑器 }, beforeDestroy() { if (this.editorInstance) { this.editorInstance.toTextArea(); // 销毁实例 } }, methods: { initEditor() { this.editorInstance = CodeMirror.fromTextArea(this.$refs.editor, { mode: "javascript", // 设置模式为 JavaScript lineNumbers: true, // 显示行号 theme: "default", // 主题设置,默认主题 extraKeys: { Ctrl: "Space" }, // 绑定快捷键触发提示 hintOptions: { completeSingle: false, // 不自动补全单个选项 tables: {}, // 可以在这里添加自定义数据表支持 customHint: this.customHintFunction, // 自定义提示函数 }, }); this.editorInstance.on("change", () => { this.$emit("input", this.editorInstance.getValue()); }); }, /** * 自定义提示逻辑 */ customHintFunction(cm) { let cur = cm.getCursor(); // 获取当前光标位置 let token = cm.getTokenAt(cur); // 获取当前词元信息 let list = ["console.log", "document.getElementById", "Math.random"]; // 自定义提示列表 return { list: list.map((item) => ({ text: item })), from: CodeMirror.Pos(cur.line, token.start), to: CodeMirror.Pos(cur.line, token.end), }; }, }, }; </script> <style scoped> .code-editor textarea { display: none; } </style> ``` #### 关键点解析 1. **初始化 CodeMirror** 使用 `CodeMirror.fromTextArea` 方法基于 `<textarea>` 元素初始化编辑器[^1]。 2. **绑定双向数据流** 当父组件更新 `v-model` 值时,同步到 CodeMirror;当用户输入时,通知父组件更新值。 3. **启用代码提示** 配置 `hintOptions` 属性中的 `customHint` 函数来自定义提示逻辑。这里提供了一个简单的字符串数组作为演示[^2]。 4. **自定义提示内容** 在 `customHintFunction` 方法中返回提示对象,包含三个属性:`list`(提示项)、`from`(起始位置)和 `to`(结束位置)。可以根据实际需求动态生成这些内容[^2]。 --- ### 示例效果 运行以上代码后,在编辑器中按下 `Ctrl + Space` 或者默认的触发条件会弹出自定义代码提示框,显示预设的内容列表。 ---
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值